summaryrefslogtreecommitdiff
path: root/ndb/src
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src')
-rw-r--r--ndb/src/Makefile.am2
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp1664
-rw-r--r--ndb/src/common/debugger/SignalLoggerManager.cpp11
-rw-r--r--ndb/src/common/debugger/signaldata/BackupImpl.cpp6
-rw-r--r--ndb/src/common/debugger/signaldata/BackupSignalData.cpp6
-rw-r--r--ndb/src/common/debugger/signaldata/DictTabInfo.cpp32
-rw-r--r--ndb/src/common/debugger/signaldata/FsRef.cpp33
-rw-r--r--ndb/src/common/debugger/signaldata/LqhFrag.cpp6
-rw-r--r--ndb/src/common/debugger/signaldata/ScanTab.cpp12
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp13
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp30
-rw-r--r--ndb/src/common/debugger/signaldata/SumaImpl.cpp76
-rw-r--r--ndb/src/common/debugger/signaldata/TcIndx.cpp85
-rw-r--r--ndb/src/common/debugger/signaldata/TcKeyReq.cpp5
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp22
-rw-r--r--ndb/src/common/mgmcommon/IPCConfig.cpp383
-rw-r--r--ndb/src/common/portlib/Makefile.am2
-rw-r--r--ndb/src/common/portlib/NdbConfig.c34
-rw-r--r--ndb/src/common/portlib/NdbTCP.cpp47
-rw-r--r--ndb/src/common/portlib/gcc.cpp7
-rw-r--r--ndb/src/common/portlib/win32/NdbTCP.c32
-rw-r--r--ndb/src/common/transporter/Makefile.am2
-rw-r--r--ndb/src/common/transporter/OSE_Transporter.cpp2
-rw-r--r--ndb/src/common/transporter/OSE_Transporter.hpp1
-rw-r--r--ndb/src/common/transporter/Packer.cpp1
-rw-r--r--ndb/src/common/transporter/SCI_Transporter.cpp8
-rw-r--r--ndb/src/common/transporter/SCI_Transporter.hpp4
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.cpp29
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.hpp6
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.unix.cpp28
-rw-r--r--ndb/src/common/transporter/SHM_Transporter.win32.cpp6
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.cpp5
-rw-r--r--ndb/src/common/transporter/TCP_Transporter.hpp4
-rw-r--r--ndb/src/common/transporter/Transporter.cpp47
-rw-r--r--ndb/src/common/transporter/Transporter.hpp34
-rw-r--r--ndb/src/common/transporter/TransporterRegistry.cpp321
-rw-r--r--ndb/src/common/util/Base64.cpp207
-rw-r--r--ndb/src/common/util/Bitmask.cpp351
-rw-r--r--ndb/src/common/util/ConfigValues.cpp8
-rw-r--r--ndb/src/common/util/File.cpp4
-rw-r--r--ndb/src/common/util/Makefile.am21
-rw-r--r--ndb/src/common/util/NdbSqlUtil.cpp1175
-rw-r--r--ndb/src/common/util/Parser.cpp7
-rw-r--r--ndb/src/common/util/SimpleProperties.cpp35
-rw-r--r--ndb/src/common/util/SocketServer.cpp84
-rw-r--r--ndb/src/common/util/md5_hash.cpp20
-rw-r--r--ndb/src/common/util/new.cpp2
-rw-r--r--ndb/src/common/util/socket_io.cpp70
-rw-r--r--ndb/src/common/util/version.c4
-rw-r--r--ndb/src/cw/cpcd/APIService.cpp15
-rw-r--r--ndb/src/cw/cpcd/APIService.hpp1
-rw-r--r--ndb/src/cw/cpcd/main.cpp3
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt14
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp292
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp19
-rw-r--r--ndb/src/kernel/blocks/backup/BackupFormat.hpp17
-rw-r--r--ndb/src/kernel/blocks/backup/BackupInit.cpp85
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp45
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp1
-rw-r--r--ndb/src/kernel/blocks/dbacc/Dbacc.hpp161
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccInit.cpp122
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp2551
-rw-r--r--ndb/src/kernel/blocks/dbacc/Makefile.am2
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp3226
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp430
-rw-r--r--ndb/src/kernel/blocks/dbdict/DictLock.txt98
-rw-r--r--ndb/src/kernel/blocks/dbdict/SchemaFile.hpp44
-rw-r--r--ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp286
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp31
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihInit.cpp21
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp618
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp50
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhInit.cpp2
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp887
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp39
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcInit.cpp15
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp535
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp90
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp117
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupGen.cpp97
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp26
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp132
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp6
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp390
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupScan.cpp315
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp4
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp14
-rw-r--r--ndb/src/kernel/blocks/dbtup/Makefile.am1
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp15
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp44
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp6
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp23
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp5
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp17
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp240
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp124
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp3
-rw-r--r--ndb/src/kernel/blocks/dbtux/Times.txt10
-rw-r--r--ndb/src/kernel/blocks/dbutil/DbUtil.cpp104
-rw-r--r--ndb/src/kernel/blocks/dbutil/DbUtil.hpp1
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp3
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp1
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp196
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp74
-rw-r--r--ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp3
-rw-r--r--ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp4
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Filename.cpp11
-rw-r--r--ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp13
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp84
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp2
-rw-r--r--ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp2
-rw-r--r--ndb/src/kernel/blocks/ndbfs/VoidFs.cpp17
-rw-r--r--ndb/src/kernel/blocks/qmgr/Qmgr.hpp34
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrInit.cpp5
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp721
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.cpp2369
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.hpp186
-rw-r--r--ndb/src/kernel/blocks/suma/SumaInit.cpp92
-rw-r--r--ndb/src/kernel/blocks/trix/Trix.cpp34
-rw-r--r--ndb/src/kernel/blocks/trix/Trix.hpp1
-rw-r--r--ndb/src/kernel/error/Error.hpp85
-rw-r--r--ndb/src/kernel/error/ErrorHandlingMacros.hpp21
-rw-r--r--ndb/src/kernel/error/ErrorMessages.cpp75
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp84
-rw-r--r--ndb/src/kernel/error/ErrorReporter.hpp17
-rw-r--r--ndb/src/kernel/error/Makefile.am2
-rw-r--r--ndb/src/kernel/error/ndbd_exit_codes.c261
-rw-r--r--ndb/src/kernel/main.cpp289
-rw-r--r--ndb/src/kernel/vm/ArrayPool.hpp23
-rw-r--r--ndb/src/kernel/vm/CArray.hpp18
-rw-r--r--ndb/src/kernel/vm/ClusterConfiguration.cpp24
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp170
-rw-r--r--ndb/src/kernel/vm/Configuration.hpp22
-rw-r--r--ndb/src/kernel/vm/DLFifoList.hpp14
-rw-r--r--ndb/src/kernel/vm/Emulator.cpp29
-rw-r--r--ndb/src/kernel/vm/FastScheduler.cpp24
-rw-r--r--ndb/src/kernel/vm/KeyDescriptor.hpp (renamed from ndb/src/ndbapi/NdbCursorOperation.cpp)54
-rw-r--r--ndb/src/kernel/vm/Makefile.am2
-rw-r--r--ndb/src/kernel/vm/MetaData.hpp7
-rw-r--r--ndb/src/kernel/vm/SafeCounter.cpp4
-rw-r--r--ndb/src/kernel/vm/SafeCounter.hpp2
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp188
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp32
-rw-r--r--ndb/src/kernel/vm/SuperPool.cpp442
-rw-r--r--ndb/src/kernel/vm/SuperPool.hpp561
-rw-r--r--ndb/src/kernel/vm/TimeQueue.cpp9
-rw-r--r--ndb/src/kernel/vm/TransporterCallback.cpp116
-rw-r--r--ndb/src/kernel/vm/VMSignal.hpp20
-rw-r--r--ndb/src/kernel/vm/WatchDog.cpp30
-rw-r--r--ndb/src/kernel/vm/WatchDog.hpp2
-rw-r--r--ndb/src/kernel/vm/ndbd_malloc.cpp63
-rw-r--r--ndb/src/kernel/vm/ndbd_malloc.hpp (renamed from ndb/src/kernel/error/ErrorMessages.hpp)12
-rw-r--r--ndb/src/kernel/vm/pc.hpp51
-rw-r--r--ndb/src/kernel/vm/testSuperPool.cpp220
-rw-r--r--ndb/src/mgmapi/LocalConfig.cpp57
-rw-r--r--ndb/src/mgmapi/Makefile.am2
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp716
-rw-r--r--ndb/src/mgmapi/mgmapi_configuration.hpp16
-rw-r--r--ndb/src/mgmapi/mgmapi_internal.h77
-rw-r--r--ndb/src/mgmapi/ndb_logevent.cpp512
-rw-r--r--ndb/src/mgmapi/ndb_logevent.hpp34
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp507
-rw-r--r--ndb/src/mgmclient/main.cpp13
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp345
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.hpp92
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp446
-rw-r--r--ndb/src/mgmsrv/InitConfigFileParser.cpp361
-rw-r--r--ndb/src/mgmsrv/InitConfigFileParser.hpp16
-rw-r--r--ndb/src/mgmsrv/Makefile.am13
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp851
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp78
-rw-r--r--ndb/src/mgmsrv/MgmtSrvrConfig.cpp10
-rw-r--r--ndb/src/mgmsrv/Services.cpp433
-rw-r--r--ndb/src/mgmsrv/Services.hpp24
-rw-r--r--ndb/src/mgmsrv/main.cpp158
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp39
-rw-r--r--ndb/src/ndbapi/ClusterMgr.hpp10
-rw-r--r--ndb/src/ndbapi/DictCache.cpp110
-rw-r--r--ndb/src/ndbapi/DictCache.hpp7
-rw-r--r--ndb/src/ndbapi/Makefile.am7
-rw-r--r--ndb/src/ndbapi/Ndb.cpp632
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.cpp2
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.hpp2
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp538
-rw-r--r--ndb/src/ndbapi/NdbBlobImpl.hpp6
-rw-r--r--ndb/src/ndbapi/NdbDictionary.cpp257
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp1426
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.hpp253
-rw-r--r--ndb/src/ndbapi/NdbEventOperation.cpp20
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.cpp523
-rw-r--r--ndb/src/ndbapi/NdbEventOperationImpl.hpp31
-rw-r--r--ndb/src/ndbapi/NdbImpl.hpp19
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp454
-rw-r--r--ndb/src/ndbapi/NdbLinHash.hpp18
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp50
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp108
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp27
-rw-r--r--ndb/src/ndbapi/NdbOperationInt.cpp86
-rw-r--r--ndb/src/ndbapi/NdbOperationSearch.cpp377
-rw-r--r--ndb/src/ndbapi/NdbPool.cpp6
-rw-r--r--ndb/src/ndbapi/NdbPoolImpl.cpp13
-rw-r--r--ndb/src/ndbapi/NdbPoolImpl.hpp8
-rw-r--r--ndb/src/ndbapi/NdbRecAttr.cpp85
-rw-r--r--ndb/src/ndbapi/NdbReceiver.cpp39
-rw-r--r--ndb/src/ndbapi/NdbResultSet.cpp114
-rw-r--r--ndb/src/ndbapi/NdbScanFilter.cpp266
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp405
-rw-r--r--ndb/src/ndbapi/NdbTransaction.cpp (renamed from ndb/src/ndbapi/NdbConnection.cpp)443
-rw-r--r--ndb/src/ndbapi/NdbTransactionScan.cpp (renamed from ndb/src/ndbapi/NdbConnectionScan.cpp)18
-rw-r--r--ndb/src/ndbapi/Ndberr.cpp5
-rw-r--r--ndb/src/ndbapi/Ndbif.cpp196
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp105
-rw-r--r--ndb/src/ndbapi/Ndblist.cpp44
-rw-r--r--ndb/src/ndbapi/TransporterFacade.cpp78
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp24
-rw-r--r--ndb/src/ndbapi/ndb_cluster_connection.cpp182
-rw-r--r--ndb/src/ndbapi/ndb_cluster_connection_impl.hpp20
-rw-r--r--ndb/src/ndbapi/ndberror.c66
220 files changed, 17642 insertions, 17455 deletions
diff --git a/ndb/src/Makefile.am b/ndb/src/Makefile.am
index eb1cf1c6543..d35790a2e43 100644
--- a/ndb/src/Makefile.am
+++ b/ndb/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = common mgmapi ndbapi . kernel mgmsrv mgmclient cw
+SUBDIRS = common mgmapi ndbapi . kernel mgmclient mgmsrv cw
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index d7e4fbd53aa..e1a477b8ea4 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -25,6 +25,8 @@
#include <NodeState.hpp>
#include <version.h>
+#include <ndbd_exit_codes.h>
+
//
// PUBLIC
//
@@ -33,838 +35,861 @@ EventLoggerBase::~EventLoggerBase()
}
-/**
- * This matrix defines which event should be printed when
- *
- * threshold - is in range [0-15]
- * severity - DEBUG to ALERT (Type of log message)
- */
-const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = {
- // CONNECTION
- { EventReport::Connected, LogLevel::llConnection, 8, Logger::LL_INFO },
- { EventReport::Disconnected, LogLevel::llConnection, 8, Logger::LL_ALERT },
- { EventReport::CommunicationClosed, LogLevel::llConnection, 8, Logger::LL_INFO },
- { EventReport::CommunicationOpened, LogLevel::llConnection, 8, Logger::LL_INFO },
- { EventReport::ConnectedApiVersion, LogLevel::llConnection, 8, Logger::LL_INFO },
- // CHECKPOINT
- { EventReport::GlobalCheckpointStarted, LogLevel::llCheckpoint, 9, Logger::LL_INFO },
- { EventReport::GlobalCheckpointCompleted,LogLevel::llCheckpoint,10, Logger::LL_INFO },
- { EventReport::LocalCheckpointStarted, LogLevel::llCheckpoint, 7, Logger::LL_INFO },
- { EventReport::LocalCheckpointCompleted,LogLevel::llCheckpoint, 8, Logger::LL_INFO },
- { EventReport::LCPStoppedInCalcKeepGci, LogLevel::llCheckpoint, 0, Logger::LL_ALERT },
- { EventReport::LCPFragmentCompleted, LogLevel::llCheckpoint, 11, Logger::LL_INFO },
- { EventReport::UndoLogBlocked, LogLevel::llCheckpoint, 7, Logger::LL_INFO },
-
- // STARTUP
- { EventReport::NDBStartStarted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::NDBStartCompleted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::STTORRYRecieved, LogLevel::llStartUp,15, Logger::LL_INFO },
- { EventReport::StartPhaseCompleted, LogLevel::llStartUp, 4, Logger::LL_INFO },
- { EventReport::CM_REGCONF, LogLevel::llStartUp, 3, Logger::LL_INFO },
- { EventReport::CM_REGREF, LogLevel::llStartUp, 8, Logger::LL_INFO },
- { EventReport::FIND_NEIGHBOURS, LogLevel::llStartUp, 8, Logger::LL_INFO },
- { EventReport::NDBStopStarted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::NDBStopAborted, LogLevel::llStartUp, 1, Logger::LL_INFO },
- { EventReport::StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO },
- { EventReport::StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO },
- { EventReport::UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO },
-
- // NODERESTART
- { EventReport::NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
- { EventReport::NR_CopyDistr, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
- { EventReport::NR_CopyFragsStarted, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
- { EventReport::NR_CopyFragDone, LogLevel::llNodeRestart, 10, Logger::LL_INFO },
- { EventReport::NR_CopyFragsCompleted, LogLevel::llNodeRestart, 8, Logger::LL_INFO },
-
- { EventReport::NodeFailCompleted, LogLevel::llNodeRestart, 8, Logger::LL_ALERT},
- { EventReport::NODE_FAILREP, LogLevel::llNodeRestart, 8, Logger::LL_ALERT},
- { EventReport::ArbitState, LogLevel::llNodeRestart, 6, Logger::LL_INFO },
- { EventReport::ArbitResult, LogLevel::llNodeRestart, 2, Logger::LL_ALERT},
- { EventReport::GCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
- { EventReport::GCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
- { EventReport::LCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
- { EventReport::LCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO },
-
- // STATISTIC
- { EventReport::TransReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO },
- { EventReport::OperationReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO },
- { EventReport::TableCreated, LogLevel::llStatistic, 7, Logger::LL_INFO },
- { EventReport::JobStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO },
- { EventReport::SendBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO },
- { EventReport::ReceiveBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO },
- { EventReport::MemoryUsage, LogLevel::llStatistic, 5, Logger::LL_INFO },
-
- // ERROR
- { EventReport::TransporterError, LogLevel::llError, 2, Logger::LL_ERROR },
- { EventReport::TransporterWarning, LogLevel::llError, 8, Logger::LL_WARNING },
- { EventReport::MissedHeartbeat, LogLevel::llError, 8, Logger::LL_WARNING },
- { EventReport::DeadDueToHeartbeat, LogLevel::llError, 8, Logger::LL_ALERT },
- { EventReport::WarningEvent, LogLevel::llError, 2, Logger::LL_WARNING },
- // INFO
- { EventReport::SentHeartbeat, LogLevel::llInfo, 12, Logger::LL_INFO },
- { EventReport::CreateLogBytes, LogLevel::llInfo, 11, Logger::LL_INFO },
- { EventReport::InfoEvent, LogLevel::llInfo, 2, Logger::LL_INFO },
-
- //Single User
- { EventReport::SingleUser, LogLevel::llInfo, 7, Logger::LL_INFO},
-
- // Backup
- { EventReport::BackupStarted, LogLevel::llBackup, 7, Logger::LL_INFO },
- { EventReport::BackupCompleted, LogLevel::llBackup, 7, Logger::LL_INFO },
- { EventReport::BackupFailedToStart, LogLevel::llBackup, 7, Logger::LL_ALERT},
- { EventReport::BackupAborted, LogLevel::llBackup, 7, Logger::LL_ALERT }
-};
-
-const Uint32 EventLoggerBase::matrixSize = sizeof(EventLoggerBase::matrix)/
- sizeof(EventRepLogLevelMatrix);
+#define QQQQ char *m_text, size_t m_text_len, const Uint32* theData
-const char*
-EventLogger::getText(char * m_text, size_t m_text_len,
- int type,
- const Uint32* theData, NodeId nodeId)
+void getTextConnected(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u Connected",
+ theData[1]);
+}
+void getTextConnectedApiVersion(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u: API version %d.%d.%d",
+ theData[1],
+ getMajor(theData[2]),
+ getMinor(theData[2]),
+ getBuild(theData[2]));
+}
+void getTextDisconnected(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u Disconnected",
+ theData[1]);
+}
+void getTextCommunicationClosed(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT communication to node closed.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Communication to Node %u closed",
+ theData[1]);
+}
+void getTextCommunicationOpened(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT communication to node opened.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Communication to Node %u opened",
+ theData[1]);
+}
+void getTextNDBStartStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // Start of NDB has been initiated.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Start initiated (version %d.%d.%d)",
+ getMajor(theData[1]),
+ getMinor(theData[1]),
+ getBuild(theData[1]));
+}
+void getTextNDBStopStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "%s shutdown initiated",
+ (theData[1] == 1 ? "Cluster" : "Node"));
+}
+void getRestartAction(Uint32 action, BaseString &str)
{
- // TODO: Change the switch implementation...
- char theNodeId[32];
- if (nodeId != 0){
- BaseString::snprintf(theNodeId, 32, "Node %u: ", nodeId);
- } else {
- theNodeId[0] = 0;
+ if (action == 0)
+ return;
+ str.appfmt(", restarting");
+ if (action & 2)
+ str.appfmt(", no start");
+ if (action & 4)
+ str.appfmt(", initial");
+}
+void getTextNDBStopCompleted(QQQQ) {
+ BaseString action_str("");
+ BaseString signum_str("");
+ getRestartAction(theData[1], action_str);
+ if (theData[2])
+ signum_str.appfmt(" Initiated by signal %d.", theData[2]);
+ BaseString::snprintf(m_text, m_text_len,
+ "Node shutdown completed%s.%s",
+ action_str.c_str(),
+ signum_str.c_str());
+}
+void getTextNDBStopForced(QQQQ) {
+ BaseString action_str("");
+ BaseString reason_str("");
+ BaseString sphase_str("");
+ int signum = theData[2];
+ int error = theData[3];
+ int sphase = theData[4];
+ int extra = theData[5];
+ getRestartAction(theData[1],action_str);
+ if (signal)
+ reason_str.appfmt(" Initiated by signal %d.", signum);
+ if (error)
+ {
+ ndbd_exit_classification cl;
+ ndbd_exit_status st;
+ const char *msg = ndbd_exit_message(error, &cl);
+ const char *cl_msg = ndbd_exit_classification_message(cl, &st);
+ const char *st_msg = ndbd_exit_status_message(st);
+ reason_str.appfmt(" Caused by error %d: \'%s(%s). %s\'.",
+ error, msg, cl_msg, st_msg);
+ if (extra != 0)
+ reason_str.appfmt(" (extra info %d)", extra);
}
-
- EventReport::EventType eventType = (EventReport::EventType)type;
- switch (eventType){
- case EventReport::Connected:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u Connected",
- theNodeId,
- theData[1]);
- break;
- case EventReport::ConnectedApiVersion:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u: API version %d.%d.%d",
- theNodeId,
- theData[1],
- getMajor(theData[2]),
- getMinor(theData[2]),
- getBuild(theData[2]));
- break;
- case EventReport::Disconnected:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u Disconnected",
- theNodeId,
- theData[1]);
- break;
- case EventReport::CommunicationClosed:
- //-----------------------------------------------------------------------
- // REPORT communication to node closed.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sCommunication to Node %u closed",
- theNodeId,
- theData[1]);
- break;
- case EventReport::CommunicationOpened:
- //-----------------------------------------------------------------------
- // REPORT communication to node opened.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sCommunication to Node %u opened",
- theNodeId,
- theData[1]);
- break;
- case EventReport::NDBStartStarted:
- //-----------------------------------------------------------------------
- // Start of NDB has been initiated.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sStart initiated (version %d.%d.%d)",
- theNodeId ,
- getMajor(theData[1]),
- getMinor(theData[1]),
- getBuild(theData[1]));
- break;
- case EventReport::NDBStopStarted:
- BaseString::snprintf(m_text, m_text_len,
- "%s%s shutdown initiated",
- theNodeId,
- (theData[1] == 1 ? "Cluster" : "Node"));
- break;
- case EventReport::NDBStopAborted:
- BaseString::snprintf(m_text, m_text_len,
- "%sNode shutdown aborted",
- theNodeId);
- break;
- case EventReport::NDBStartCompleted:
- //-----------------------------------------------------------------------
- // Start of NDB has been completed.
- //-----------------------------------------------------------------------
+ if (sphase < 255)
+ sphase_str.appfmt(" Occured during startphase %u.", sphase);
+ BaseString::snprintf(m_text, m_text_len,
+ "Forced node shutdown completed%s.%s%s",
+ action_str.c_str(), sphase_str.c_str(),
+ reason_str.c_str());
+}
+void getTextNDBStopAborted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node shutdown aborted");
+}
+void getTextNDBStartCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // Start of NDB has been completed.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Started (version %d.%d.%d)",
+ getMajor(theData[1]),
+ getMinor(theData[1]),
+ getBuild(theData[1]));
+}
+void getTextSTTORRYRecieved(QQQQ) {
+ //-----------------------------------------------------------------------
+ // STTORRY recevied after restart finished.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "STTORRY received after restart finished");
+}
+void getTextStartPhaseCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Start phase completed.
+ //-----------------------------------------------------------------------
+ const char *type = "<Unknown>";
+ switch((NodeState::StartType)theData[2]){
+ case NodeState::ST_INITIAL_START:
+ type = "(initial start)";
+ break;
+ case NodeState::ST_SYSTEM_RESTART:
+ type = "(system restart)";
+ break;
+ case NodeState::ST_NODE_RESTART:
+ type = "(node restart)";
+ break;
+ case NodeState::ST_INITIAL_NODE_RESTART:
+ type = "(initial node restart)";
+ break;
+ case NodeState::ST_ILLEGAL_TYPE:
+ type = "";
+ break;
+ default:
BaseString::snprintf(m_text, m_text_len,
- "%sStarted (version %d.%d.%d)",
- theNodeId ,
- getMajor(theData[1]),
- getMinor(theData[1]),
- getBuild(theData[1]));
-
- break;
- case EventReport::STTORRYRecieved:
- //-----------------------------------------------------------------------
- // STTORRY recevied after restart finished.
- //-----------------------------------------------------------------------
+ "Start phase %u completed (unknown = %d)",
+ theData[1],
+ theData[2]);
+ return;
+ }
+ BaseString::snprintf(m_text, m_text_len,
+ "Start phase %u completed %s",
+ theData[1],
+ type);
+}
+void getTextCM_REGCONF(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "CM_REGCONF president = %u, own Node = %u, our dynamic id = %u",
+ theData[2],
+ theData[1],
+ theData[3]);
+}
+void getTextCM_REGREF(QQQQ) {
+ const char* line = "";
+ switch (theData[3]) {
+ case 0:
+ line = "Busy";
+ break;
+ case 1:
+ line = "Election with wait = false";
+ break;
+ case 2:
+ line = "Election with wait = false";
+ break;
+ case 3:
+ line = "Not president";
+ break;
+ case 4:
+ line = "Election without selecting new candidate";
+ break;
+ default:
+ line = "No such cause";
+ break;
+ }//switch
+
+ BaseString::snprintf(m_text, m_text_len,
+ "CM_REGREF from Node %u to our Node %u. Cause = %s",
+ theData[2],
+ theData[1],
+ line);
+}
+void getTextFIND_NEIGHBOURS(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart copied a fragment.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "We are Node %u with dynamic ID %u, our left neighbour "
+ "is Node %u, our right is Node %u",
+ theData[1],
+ theData[4],
+ theData[2],
+ theData[3]);
+}
+void getTextNodeFailCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node failure phase completed.
+ //-----------------------------------------------------------------------
+ if (theData[1] == 0)
+ {
+ if (theData[3] != 0) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u completed failure of Node %u",
+ theData[3],
+ theData[2]);
+ } else {
+ BaseString::snprintf(m_text, m_text_len,
+ "All nodes completed failure of Node %u",
+ theData[2]);
+ }//if
+ } else {
+ const char* line = "";
+ if (theData[1] == DBTC){
+ line = "DBTC";
+ }else if (theData[1] == DBDICT){
+ line = "DBDICT";
+ }else if (theData[1] == DBDIH){
+ line = "DBDIH";
+ }else if (theData[1] == DBLQH){
+ line = "DBLQH";
+ }
BaseString::snprintf(m_text, m_text_len,
- "%sSTTORRY received after restart finished",
- theNodeId);
- break;
- case EventReport::StartPhaseCompleted:{
- //-----------------------------------------------------------------------
- // REPORT Start phase completed.
- //-----------------------------------------------------------------------
- const char * type = "<Unknown>";
- switch((NodeState::StartType)theData[2]){
- case NodeState::ST_INITIAL_START:
- type = "(initial start)";
+ "Node failure of %u %s completed",
+ theData[2],
+ line);
+ }
+}
+void getTextNODE_FAILREP(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %u has failed. The Node state at failure "
+ "was %u",
+ theData[1],
+ theData[2]);
+}
+void getTextArbitState(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT arbitrator found or lost.
+ //-----------------------------------------------------------------------
+ {
+ const ArbitSignalData* sd = (ArbitSignalData*)theData;
+ char ticketText[ArbitTicket::TextLength + 1];
+ char errText[ArbitCode::ErrTextLength + 1];
+ const unsigned code = sd->code & 0xFFFF;
+ const unsigned state = sd->code >> 16;
+ switch (code) {
+ case ArbitCode::ThreadStart:
+ BaseString::snprintf(m_text, m_text_len,
+ "President restarts arbitration thread [state=%u]",
+ state);
break;
- case NodeState::ST_SYSTEM_RESTART:
- type = "(system restart)";
+ case ArbitCode::PrepPart2:
+ sd->ticket.getText(ticketText, sizeof(ticketText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Prepare arbitrator node %u [ticket=%s]",
+ sd->node, ticketText);
break;
- case NodeState::ST_NODE_RESTART:
- type = "(node restart)";
+ case ArbitCode::PrepAtrun:
+ sd->ticket.getText(ticketText, sizeof(ticketText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Receive arbitrator node %u [ticket=%s]",
+ sd->node, ticketText);
break;
- case NodeState::ST_INITIAL_NODE_RESTART:
- type = "(initial node restart)";
+ case ArbitCode::ApiStart:
+ sd->ticket.getText(ticketText, sizeof(ticketText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Started arbitrator node %u [ticket=%s]",
+ sd->node, ticketText);
break;
- case NodeState::ST_ILLEGAL_TYPE:
- type = "";
+ case ArbitCode::ApiFail:
+ BaseString::snprintf(m_text, m_text_len,
+ "Lost arbitrator node %u - process failure [state=%u]",
+ sd->node, state);
+ break;
+ case ArbitCode::ApiExit:
+ BaseString::snprintf(m_text, m_text_len,
+ "Lost arbitrator node %u - process exit [state=%u]",
+ sd->node, state);
+ break;
+ default:
+ ArbitCode::getErrText(code, errText, sizeof(errText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Lost arbitrator node %u - %s [state=%u]",
+ sd->node, errText, state);
break;
- default:{
- BaseString::snprintf(m_text, m_text_len,
- "%sStart phase %u completed (unknown = %d)",
- theNodeId,
- theData[1],
- theData[2]);
- return m_text;
- }
}
- BaseString::snprintf(m_text, m_text_len,
- "%sStart phase %u completed %s",
- theNodeId,
- theData[1],
- type);
- return m_text;
- break;
}
- case EventReport::CM_REGCONF:
- BaseString::snprintf(m_text, m_text_len,
- "%sCM_REGCONF president = %u, own Node = %u, our dynamic id = %u"
- ,
- theNodeId,
- theData[2],
- theData[1],
- theData[3]);
- break;
- case EventReport::CM_REGREF:
+}
+
+void getTextArbitResult(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT arbitration result (the failures may not reach us).
+ //-----------------------------------------------------------------------
{
- const char* line = "";
- switch (theData[3]) {
- case 0:
- line = "Busy";
+ const ArbitSignalData* sd = (ArbitSignalData*)theData;
+ char errText[ArbitCode::ErrTextLength + 1];
+ const unsigned code = sd->code & 0xFFFF;
+ const unsigned state = sd->code >> 16;
+ switch (code) {
+ case ArbitCode::LoseNodes:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check lost - less than 1/2 nodes left");
+ break;
+ case ArbitCode::WinNodes:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check won - all node groups and more than 1/2 nodes left");
+ break;
+ case ArbitCode::WinGroups:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check won - node group majority");
+ break;
+ case ArbitCode::LoseGroups:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration check lost - missing node group");
break;
- case 1:
- line = "Election with wait = false";
+ case ArbitCode::Partitioning:
+ BaseString::snprintf(m_text, m_text_len,
+ "Network partitioning - arbitration required");
break;
- case 2:
- line = "Election with wait = false";
+ case ArbitCode::WinChoose:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration won - positive reply from node %u",
+ sd->node);
break;
- case 3:
- line = "Not president";
+ case ArbitCode::LoseChoose:
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration lost - negative reply from node %u",
+ sd->node);
break;
- case 4:
- line = "Election without selecting new candidate";
+ case ArbitCode::LoseNorun:
+ BaseString::snprintf(m_text, m_text_len,
+ "Network partitioning - no arbitrator available");
+ break;
+ case ArbitCode::LoseNocfg:
+ BaseString::snprintf(m_text, m_text_len,
+ "Network partitioning - no arbitrator configured");
break;
default:
- line = "No such cause";
+ ArbitCode::getErrText(code, errText, sizeof(errText));
+ BaseString::snprintf(m_text, m_text_len,
+ "Arbitration failure - %s [state=%u]",
+ errText, state);
break;
- }//switch
-
- BaseString::snprintf(m_text, m_text_len,
- "%sCM_REGREF from Node %u to our Node %u. Cause = %s",
- theNodeId,
- theData[2],
- theData[1],
- line);
- }
- break;
- case EventReport::FIND_NEIGHBOURS:
- //-----------------------------------------------------------------------
- // REPORT Node Restart copied a fragment.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sWe are Node %u with dynamic ID %u, our left neighbour "
- "is Node %u, our right is Node %u",
- theNodeId,
- theData[1],
- theData[4],
- theData[2],
- theData[3]);
- break;
- case EventReport::NodeFailCompleted:
- //-----------------------------------------------------------------------
- // REPORT Node failure phase completed.
- //-----------------------------------------------------------------------
- if (theData[1] == 0)
- {
- if (theData[3] != 0) {
- BaseString::snprintf(m_text, m_text_len,
- "%sNode %u completed failure of Node %u",
- theNodeId,
- theData[3],
- theData[2]);
- } else {
- BaseString::snprintf(m_text, m_text_len,
- "%sAll nodes completed failure of Node %u",
- theNodeId,
- theData[2]);
- }//if
- } else {
- const char* line = "";
- if (theData[1] == DBTC){
- line = "DBTC";
- }else if (theData[1] == DBDICT){
- line = "DBDICT";
- }else if (theData[1] == DBDIH){
- line = "DBDIH";
- }else if (theData[1] == DBLQH){
- line = "DBLQH";
- }
-
- BaseString::snprintf(m_text, m_text_len,
- "%sNode failure of %u %s completed",
- theNodeId,
- theData[2],
- line);
- }
- break;
- case EventReport::NODE_FAILREP:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode %u has failed. The Node state at failure "
- "was %u",
- theNodeId,
- theData[1],
- theData[2]);
-
- break;
- case EventReport::ArbitState:
- //-----------------------------------------------------------------------
- // REPORT arbitrator found or lost.
- //-----------------------------------------------------------------------
- { const ArbitSignalData* sd = (ArbitSignalData*)theData;
- char ticketText[ArbitTicket::TextLength + 1];
- char errText[ArbitCode::ErrTextLength + 1];
- const unsigned code = sd->code & 0xFFFF;
- const unsigned state = sd->code >> 16;
- switch (code) {
- case ArbitCode::ThreadStart:
- BaseString::snprintf(m_text, m_text_len,
- "%sPresident restarts arbitration thread [state=%u]",
- theNodeId, state);
- break;
- case ArbitCode::PrepPart2:
- sd->ticket.getText(ticketText, sizeof(ticketText));
- BaseString::snprintf(m_text, m_text_len,
- "%sPrepare arbitrator node %u [ticket=%s]",
- theNodeId, sd->node, ticketText);
- break;
- case ArbitCode::PrepAtrun:
- sd->ticket.getText(ticketText, sizeof(ticketText));
- BaseString::snprintf(m_text, m_text_len,
- "%sReceive arbitrator node %u [ticket=%s]",
- theNodeId, sd->node, ticketText);
- break;
- case ArbitCode::ApiStart:
- sd->ticket.getText(ticketText, sizeof(ticketText));
- BaseString::snprintf(m_text, m_text_len,
- "%sStarted arbitrator node %u [ticket=%s]",
- theNodeId, sd->node, ticketText);
- break;
- case ArbitCode::ApiFail:
- BaseString::snprintf(m_text, m_text_len,
- "%sLost arbitrator node %u - process failure [state=%u]",
- theNodeId, sd->node, state);
- break;
- case ArbitCode::ApiExit:
- BaseString::snprintf(m_text, m_text_len,
- "%sLost arbitrator node %u - process exit [state=%u]",
- theNodeId, sd->node, state);
- break;
- default:
- ArbitCode::getErrText(code, errText, sizeof(errText));
- BaseString::snprintf(m_text, m_text_len,
- "%sLost arbitrator node %u - %s [state=%u]",
- theNodeId, sd->node, errText, state);
- break;
- }
- }
- break;
- case EventReport::ArbitResult:
- //-----------------------------------------------------------------------
- // REPORT arbitration result (the failures may not reach us).
- //-----------------------------------------------------------------------
- { const ArbitSignalData* sd = (ArbitSignalData*)theData;
- char errText[ArbitCode::ErrTextLength + 1];
- const unsigned code = sd->code & 0xFFFF;
- const unsigned state = sd->code >> 16;
- switch (code) {
- case ArbitCode::LoseNodes:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check lost - less than 1/2 nodes left",
- theNodeId);
- break;
- case ArbitCode::WinNodes:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check won - all node groups and more than 1/2 nodes left",
- theNodeId);
- break;
- case ArbitCode::WinGroups:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check won - node group majority",
- theNodeId);
- break;
- case ArbitCode::LoseGroups:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration check lost - missing node group",
- theNodeId);
- break;
- case ArbitCode::Partitioning:
- BaseString::snprintf(m_text, m_text_len,
- "%sNetwork partitioning - arbitration required",
- theNodeId);
- break;
- case ArbitCode::WinChoose:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration won - positive reply from node %u",
- theNodeId, sd->node);
- break;
- case ArbitCode::LoseChoose:
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration lost - negative reply from node %u",
- theNodeId, sd->node);
- break;
- case ArbitCode::LoseNorun:
- BaseString::snprintf(m_text, m_text_len,
- "%sNetwork partitioning - no arbitrator available",
- theNodeId);
- break;
- case ArbitCode::LoseNocfg:
- BaseString::snprintf(m_text, m_text_len,
- "%sNetwork partitioning - no arbitrator configured",
- theNodeId);
- break;
- default:
- ArbitCode::getErrText(code, errText, sizeof(errText));
- BaseString::snprintf(m_text, m_text_len,
- "%sArbitration failure - %s [state=%u]",
- theNodeId, errText, state);
- break;
- }
}
- break;
- case EventReport::GlobalCheckpointStarted:
- //-----------------------------------------------------------------------
- // This event reports that a global checkpoint has been started and this
- // node is the master of this global checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sGlobal checkpoint %u started",
- theNodeId,
- theData[1]);
- break;
- case EventReport::GlobalCheckpointCompleted:
- //-----------------------------------------------------------------------
- // This event reports that a global checkpoint has been completed on this
- // node and the node is the master of this global checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text, m_text_len,
- "%sGlobal checkpoint %u completed",
- theNodeId,
- theData[1]);
- break;
- case EventReport::LocalCheckpointStarted:
- //-----------------------------------------------------------------------
- // This event reports that a local checkpoint has been started and this
- // node is the master of this local checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLocal checkpoint %u started. "
- "Keep GCI = %u oldest restorable GCI = %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3]);
- break;
- case EventReport::LocalCheckpointCompleted:
- //-----------------------------------------------------------------------
- // This event reports that a local checkpoint has been completed on this
- // node and the node is the master of this local checkpoint.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLocal checkpoint %u completed",
- theNodeId,
- theData[1]);
- break;
- case EventReport::TableCreated:
- //-----------------------------------------------------------------------
- // This event reports that a table has been created.
- //-----------------------------------------------------------------------
+ }
+}
+void getTextGlobalCheckpointStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a global checkpoint has been started and this
+ // node is the master of this global checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Global checkpoint %u started",
+ theData[1]);
+}
+void getTextGlobalCheckpointCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a global checkpoint has been completed on this
+ // node and the node is the master of this global checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Global checkpoint %u completed",
+ theData[1]);
+}
+void getTextLocalCheckpointStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a local checkpoint has been started and this
+ // node is the master of this local checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Local checkpoint %u started. "
+ "Keep GCI = %u oldest restorable GCI = %u",
+ theData[1],
+ theData[2],
+ theData[3]);
+}
+void getTextLocalCheckpointCompleted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a local checkpoint has been completed on this
+ // node and the node is the master of this local checkpoint.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Local checkpoint %u completed",
+ theData[1]);
+}
+void getTextTableCreated(QQQQ) {
+ //-----------------------------------------------------------------------
+ // This event reports that a table has been created.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Table with ID = %u created",
+ theData[1]);
+}
+/* STRANGE */
+void getTextLCPStoppedInCalcKeepGci(QQQQ) {
+ if (theData[1] == 0)
BaseString::snprintf(m_text, m_text_len,
- "%sTable with ID = %u created",
- theNodeId,
- theData[1]);
- break;
- case EventReport::LCPStoppedInCalcKeepGci:
- if (theData[1] == 0)
- BaseString::snprintf(m_text, m_text_len,
- "%sLocal Checkpoint stopped in CALCULATED_KEEP_GCI",
- theNodeId);
+ "Local Checkpoint stopped in CALCULATED_KEEP_GCI");
+}
+void getTextNR_CopyDict(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart completed copy of dictionary information.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart completed copy of dictionary information");
+}
+void getTextNR_CopyDistr(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart completed copy of distribution information.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart completed copy of distribution information");
+}
+void getTextNR_CopyFragsStarted(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart is starting to copy the fragments.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart starting to copy the fragments "
+ "to Node %u",
+ theData[1]);
+}
+void getTextNR_CopyFragDone(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Node Restart copied a fragment.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Table ID = %u, fragment ID = %u have been copied "
+ "to Node %u",
+ theData[2],
+ theData[3],
+ theData[1]);
+}
+void getTextNR_CopyFragsCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node restart completed copying the fragments "
+ "to Node %u",
+ theData[1]);
+}
+void getTextLCPFragmentCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Table ID = %u, fragment ID = %u has completed LCP "
+ "on Node %u maxGciStarted: %d maxGciCompleted: %d",
+ theData[2],
+ theData[3],
+ theData[1],
+ theData[4],
+ theData[5]);
+}
+void getTextTransReportCounters(QQQQ) {
+ // -------------------------------------------------------------------
+ // Report information about transaction activity once per 10 seconds.
+ // -------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Trans. Count = %u, Commit Count = %u, "
+ "Read Count = %u, Simple Read Count = %u,\n"
+ "Write Count = %u, AttrInfo Count = %u, "
+ "Concurrent Operations = %u, Abort Count = %u\n"
+ " Scans: %u Range scans: %u",
+ theData[1],
+ theData[2],
+ theData[3],
+ theData[4],
+ theData[5],
+ theData[6],
+ theData[7],
+ theData[8],
+ theData[9],
+ theData[10]);
+}
+void getTextOperationReportCounters(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Operations=%u",
+ theData[1]);
+}
+void getTextUndoLogBlocked(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Undo Logging blocked due to buffer near to overflow.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "ACC Blocked %u and TUP Blocked %u times last second",
+ theData[1],
+ theData[2]);
+}
+void getTextTransporterError(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Transporter to node %d reported error 0x%x",
+ theData[1],
+ theData[2]);
+}
+void getTextTransporterWarning(QQQQ) {
+ getTextTransporterError(m_text, m_text_len, theData);
+}
+void getTextMissedHeartbeat(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Undo Logging blocked due to buffer near to overflow.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %d missed heartbeat %d",
+ theData[1],
+ theData[2]);
+}
+void getTextDeadDueToHeartbeat(QQQQ) {
+ //-----------------------------------------------------------------------
+ // REPORT Undo Logging blocked due to buffer near to overflow.
+ //-----------------------------------------------------------------------
+ BaseString::snprintf(m_text, m_text_len,
+ "Node %d declared dead due to missed heartbeat",
+ theData[1]);
+}
+void getTextJobStatistic(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Mean loop Counter in doJob last 8192 times = %u",
+ theData[1]);
+}
+void getTextSendBytesStatistic(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Mean send size to Node = %d last 4096 sends = %u bytes",
+ theData[1],
+ theData[2]);
+}
+void getTextReceiveBytesStatistic(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Mean receive size to Node = %d last 4096 sends = %u bytes",
+ theData[1],
+ theData[2]);
+}
+void getTextSentHeartbeat(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node Sent Heartbeat to node = %d",
+ theData[1]);
+}
+void getTextCreateLogBytes(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Log part %u, log file %u, MB %u",
+ theData[1],
+ theData[2],
+ theData[3]);
+}
+void getTextStartLog(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Log part %u, start MB %u, stop MB %u, last GCI, log exec %u",
+ theData[1],
+ theData[2],
+ theData[3],
+ theData[4]);
+}
+void getTextStartREDOLog(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Node: %d StartLog: [GCI Keep: %d LastCompleted: %d NewestRestorable: %d]",
+ theData[1],
+ theData[2],
+ theData[3],
+ theData[4]);
+}
+void getTextUNDORecordsExecuted(QQQQ) {
+ const char* line = "";
+ if (theData[1] == DBTUP){
+ line = "DBTUP";
+ }else if (theData[1] == DBACC){
+ line = "DBACC";
+ }
+
+ BaseString::snprintf(m_text, m_text_len,
+ " UNDO %s %d [%d %d %d %d %d %d %d %d %d]",
+ line,
+ theData[2],
+ theData[3],
+ theData[4],
+ theData[5],
+ theData[6],
+ theData[7],
+ theData[8],
+ theData[9],
+ theData[10],
+ theData[11]);
+}
+void getTextInfoEvent(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, (char *)&theData[1]);
+}
+void getTextWarningEvent(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, (char *)&theData[1]);
+}
+void getTextGCP_TakeoverStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, "GCP Take over started");
+}
+void getTextGCP_TakeoverCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, "GCP Take over completed");
+}
+void getTextLCP_TakeoverStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len, "LCP Take over started");
+}
+void getTextLCP_TakeoverCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "LCP Take over completed (state = %d)",
+ theData[1]);
+}
+void getTextMemoryUsage(QQQQ) {
+ const int gth = theData[1];
+ const int size = theData[2];
+ const int used = theData[3];
+ const int total = theData[4];
+ const int block = theData[5];
+ const int percent = (used*100)/total;
+
+ BaseString::snprintf(m_text, m_text_len,
+ "%s usage %s %d%s(%d %dK pages of total %d)",
+ (block==DBACC ? "Index" : (block == DBTUP ?"Data":"<unknown>")),
+ (gth == 0 ? "is" : (gth > 0 ? "increased to" : "decreased to")),
+ percent, "%",
+ used, size/1024, total
+ );
+}
+
+void getTextBackupStarted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup %d started from node %d",
+ theData[2], refToNode(theData[1]));
+}
+void getTextBackupFailedToStart(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup request from %d failed to start. Error: %d",
+ refToNode(theData[1]), theData[2]);
+}
+void getTextBackupCompleted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup %u started from node %u completed\n"
+ " StartGCP: %u StopGCP: %u\n"
+ " #Records: %u #LogRecords: %u\n"
+ " Data: %u bytes Log: %u bytes",
+ theData[2], refToNode(theData[1]),
+ theData[3], theData[4], theData[6], theData[8],
+ theData[5], theData[7]);
+}
+void getTextBackupAborted(QQQQ) {
+ BaseString::snprintf(m_text, m_text_len,
+ "Backup %d started from %d has been aborted. Error: %d",
+ theData[2],
+ refToNode(theData[1]),
+ theData[3]);
+}
+
+void getTextSingleUser(QQQQ) {
+ switch (theData[1])
+ {
+ case 0:
+ BaseString::snprintf(m_text, m_text_len, "Entering single user mode");
break;
- case EventReport::NR_CopyDict:
- //-----------------------------------------------------------------------
- // REPORT Node Restart completed copy of dictionary information.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart completed copy of dictionary information",
- theNodeId);
+ case 1:
+ BaseString::snprintf(m_text, m_text_len,
+ "Entered single user mode "
+ "Node %d has exclusive access", theData[2]);
break;
- case EventReport::NR_CopyDistr:
- //-----------------------------------------------------------------------
- // REPORT Node Restart completed copy of distribution information.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart completed copy of distribution information",
- theNodeId);
+ case 2:
+ BaseString::snprintf(m_text, m_text_len,"Exiting single user mode");
break;
- case EventReport::NR_CopyFragsStarted:
- //-----------------------------------------------------------------------
- // REPORT Node Restart is starting to copy the fragments.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart starting to copy the fragments "
- "to Node %u",
- theNodeId,
- theData[1]);
+ default:
+ BaseString::snprintf(m_text, m_text_len,
+ "Unknown single user report %d", theData[1]);
break;
- case EventReport::NR_CopyFragDone:
- //-----------------------------------------------------------------------
- // REPORT Node Restart copied a fragment.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTable ID = %u, fragment ID = %u have been copied "
- "to Node %u",
- theNodeId,
- theData[2],
- theData[3],
- theData[1]);
- break;
- case EventReport::NR_CopyFragsCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode restart completed copying the fragments "
- "to Node %u",
- theNodeId,
- theData[1]);
+ }
+}
+
+void getTextStartReport(QQQQ) {
+ Uint32 time = theData[2];
+ Uint32 sz = theData[3];
+ char mask1[100];
+ char mask2[100];
+ char mask3[100];
+ char mask4[100];
+ BitmaskImpl::getText(sz, theData + 4 + (0 * sz), mask1);
+ BitmaskImpl::getText(sz, theData + 4 + (1 * sz), mask2);
+ BitmaskImpl::getText(sz, theData + 4 + (2 * sz), mask3);
+ BitmaskImpl::getText(sz, theData + 4 + (3 * sz), mask4);
+ switch(theData[1]){
+ case 1: // Wait initial
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Initial start, waiting for %s to connect, "
+ " nodes [ all: %s connected: %s no-wait: %s ]",
+ mask4, mask1, mask2, mask3);
break;
- case EventReport::LCPFragmentCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTable ID = %u, fragment ID = %u has completed LCP "
- "on Node %u maxGciStarted: %d maxGciCompleted: %d",
- theNodeId,
- theData[2],
- theData[3],
- theData[1],
- theData[4],
- theData[5]);
+ case 2: // Wait partial
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Waiting until nodes: %s connects, "
+ "nodes [ all: %s connected: %s no-wait: %s ]",
+ mask4, mask1, mask2, mask3);
break;
- case EventReport::TransReportCounters:
- // -------------------------------------------------------------------
- // Report information about transaction activity once per 10 seconds.
- // -------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTrans. Count = %u, Commit Count = %u, "
- "Read Count = %u, Simple Read Count = %u,\n"
- "Write Count = %u, AttrInfo Count = %u, "
- "Concurrent Operations = %u, Abort Count = %u\n"
- " Scans: %u Range scans: %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3],
- theData[4],
- theData[5],
- theData[6],
- theData[7],
- theData[8],
- theData[9],
- theData[10]);
+ case 3: // Wait partial timeout
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Waiting %u sec for nodes %s to connect, "
+ "nodes [ all: %s connected: %s no-wait: %s ]",
+
+ time, mask4, mask1, mask2, mask3);
break;
- case EventReport::OperationReportCounters:
- BaseString::snprintf(m_text, m_text_len,
- "%sOperations=%u",
- theNodeId,
- theData[1]);
+ case 4: // Wait partioned
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Waiting for non partitioned start, "
+ "nodes [ all: %s connected: %s missing: %s no-wait: %s ]",
+
+ mask1, mask2, mask4, mask3);
break;
- case EventReport::UndoLogBlocked:
- //-----------------------------------------------------------------------
- // REPORT Undo Logging blocked due to buffer near to overflow.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sACC Blocked %u and TUP Blocked %u times last second",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::TransporterError:
- case EventReport::TransporterWarning:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sTransporter to node %d reported error 0x%x",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::MissedHeartbeat:
- //-----------------------------------------------------------------------
- // REPORT Undo Logging blocked due to buffer near to overflow.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode %d missed heartbeat %d",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::DeadDueToHeartbeat:
- //-----------------------------------------------------------------------
- // REPORT Undo Logging blocked due to buffer near to overflow.
- //-----------------------------------------------------------------------
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode %d declared dead due to missed heartbeat",
- theNodeId,
- theData[1]);
- break;
- case EventReport::JobStatistic:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sMean loop Counter in doJob last 8192 times = %u",
- theNodeId,
- theData[1]);
+ case 5:
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Waiting %u sec for non partitioned start, "
+ "nodes [ all: %s connected: %s missing: %s no-wait: %s ]",
+
+ time, mask1, mask2, mask4, mask3);
break;
- case EventReport::SendBytesStatistic:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sMean send size to Node = %d last 4096 sends = %u bytes",
- theNodeId,
- theData[1],
- theData[2]);
+ case 0x8000: // Do initial
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Initial start with nodes %s [ missing: %s no-wait: %s ]",
+ mask2, mask4, mask3);
break;
- case EventReport::ReceiveBytesStatistic:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sMean receive size to Node = %d last 4096 sends = %u bytes",
- theNodeId,
- theData[1],
- theData[2]);
- break;
- case EventReport::SentHeartbeat:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode Sent Heartbeat to node = %d",
- theNodeId,
- theData[1]);
- break;
- case EventReport::CreateLogBytes:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLog part %u, log file %u, MB %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3]);
- break;
- case EventReport::StartLog:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLog part %u, start MB %u, stop MB %u, last GCI, log exec %u",
- theNodeId,
- theData[1],
- theData[2],
- theData[3],
- theData[4]);
- break;
- case EventReport::StartREDOLog:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sNode: %d StartLog: [GCI Keep: %d LastCompleted: %d NewestRestorable: %d]",
- theNodeId,
- theData[1],
- theData[2],
- theData[3],
- theData[4]);
- break;
- case EventReport::UNDORecordsExecuted:{
- const char* line = "";
- if (theData[1] == DBTUP){
- line = "DBTUP";
- }else if (theData[1] == DBACC){
- line = "DBACC";
- }
-
- BaseString::snprintf(m_text,
- m_text_len,
- "%s UNDO %s %d [%d %d %d %d %d %d %d %d %d]",
- theNodeId,
- line,
- theData[2],
- theData[3],
- theData[4],
- theData[5],
- theData[6],
- theData[7],
- theData[8],
- theData[9],
- theData[10],
- theData[11]);
- }
+ case 0x8001: // Do start
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Start with all nodes %s",
+ mask2);
break;
- case EventReport::InfoEvent:
- BaseString::snprintf(m_text,
- m_text_len,
- "%s%s",
- theNodeId,
- (char *)&theData[1]);
- break;
- case EventReport::WarningEvent:
- BaseString::snprintf(m_text,
- m_text_len,
- "%s%s",
- theNodeId,
- (char *)&theData[1]);
- break;
- case EventReport::GCP_TakeoverStarted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sGCP Take over started", theNodeId);
- break;
- case EventReport::GCP_TakeoverCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sGCP Take over completed", theNodeId);
- break;
- case EventReport::LCP_TakeoverStarted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLCP Take over started", theNodeId);
- break;
- case EventReport::LCP_TakeoverCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sLCP Take over completed (state = %d)",
- theNodeId, theData[1]);
- break;
- case EventReport::MemoryUsage:{
- const int gth = theData[1];
- const int size = theData[2];
- const int used = theData[3];
- const int total = theData[4];
- const int block = theData[5];
- const int percent = (used*100)/total;
-
- BaseString::snprintf(m_text, m_text_len,
- "%s%s usage %s %d%s(%d %dK pages of total %d)",
- theNodeId,
- (block==DBACC ? "Index" : (block == DBTUP ?"Data":"<unknown>")),
- (gth == 0 ? "is" : (gth > 0 ? "increased to" : "decreased to")),
- percent, "%",
- used, size/1024, total
- );
+ case 0x8002: // Do partial
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Start with nodes %s [ missing: %s no-wait: %s ]",
+ mask2, mask4, mask3);
break;
- }
- case EventReport::SingleUser :
- {
- switch (theData[1])
- {
- case 0:
- BaseString::snprintf(m_text, m_text_len,
- "%sEntering single user mode", theNodeId);
- break;
- case 1:
- BaseString::snprintf(m_text, m_text_len,
- "%sEntered single user mode %d", theNodeId, theData[2]);
- break;
- case 2:
- BaseString::snprintf(m_text, m_text_len,
- "%sExiting single user mode", theNodeId);
- break;
- default:
- BaseString::snprintf(m_text, m_text_len,
- "%sUnknown single user report %d", theNodeId, theData[1]);
- break;
- }
+ case 0x8003: // Do partioned
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Start potentially partitioned with nodes %s "
+ " [ missing: %s no-wait: %s ]",
+ mask2, mask4, mask3);
break;
- }
- case EventReport::BackupStarted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup %d started from node %d",
- theNodeId, theData[2], refToNode(theData[1]));
- break;
- case EventReport::BackupFailedToStart:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup request from %d failed to start. Error: %d",
- theNodeId, refToNode(theData[1]), theData[2]);
- break;
- case EventReport::BackupCompleted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup %u started from node %u completed\n"
- " StartGCP: %u StopGCP: %u\n"
- " #Records: %u #LogRecords: %u\n"
- " Data: %u bytes Log: %u bytes",
- theNodeId, theData[2], refToNode(theData[1]),
- theData[3], theData[4], theData[6], theData[8],
- theData[5], theData[7]);
- break;
- case EventReport::BackupAborted:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sBackup %d started from %d has been aborted. Error: %d",
- theNodeId,
- theData[2],
- refToNode(theData[1]),
- theData[3]);
- break;
default:
- BaseString::snprintf(m_text,
- m_text_len,
- "%sUnknown event: %d",
- theNodeId,
- theData[0]);
-
+ BaseString::snprintf
+ (m_text, m_text_len,
+ "Unknown startreport: 0x%x [ %s %s %s %s ]",
+ theData[1],
+ mask1, mask2, mask3, mask4);
}
- return m_text;
}
+#if 0
+BaseString::snprintf(m_text,
+ m_text_len,
+ "Unknown event: %d",
+ theData[0]);
+#endif
+
+/**
+ * This matrix defines which event should be printed when
+ *
+ * threshold - is in range [0-15]
+ * severity - DEBUG to ALERT (Type of log message)
+ */
+
+#define ROW(a,b,c,d) \
+{ NDB_LE_ ## a, b, c, d, getText ## a}
+
+const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = {
+ // CONNECTION
+ ROW(Connected, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ ROW(Disconnected, LogLevel::llConnection, 8, Logger::LL_ALERT ),
+ ROW(CommunicationClosed, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ ROW(CommunicationOpened, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ ROW(ConnectedApiVersion, LogLevel::llConnection, 8, Logger::LL_INFO ),
+ // CHECKPOINT
+ ROW(GlobalCheckpointStarted, LogLevel::llCheckpoint, 9, Logger::LL_INFO ),
+ ROW(GlobalCheckpointCompleted,LogLevel::llCheckpoint,10, Logger::LL_INFO ),
+ ROW(LocalCheckpointStarted, LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
+ ROW(LocalCheckpointCompleted,LogLevel::llCheckpoint, 8, Logger::LL_INFO ),
+ ROW(LCPStoppedInCalcKeepGci, LogLevel::llCheckpoint, 0, Logger::LL_ALERT ),
+ ROW(LCPFragmentCompleted, LogLevel::llCheckpoint, 11, Logger::LL_INFO ),
+ ROW(UndoLogBlocked, LogLevel::llCheckpoint, 7, Logger::LL_INFO ),
+
+ // STARTUP
+ ROW(NDBStartStarted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(NDBStartCompleted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(STTORRYRecieved, LogLevel::llStartUp, 15, Logger::LL_INFO ),
+ ROW(StartPhaseCompleted, LogLevel::llStartUp, 4, Logger::LL_INFO ),
+ ROW(CM_REGCONF, LogLevel::llStartUp, 3, Logger::LL_INFO ),
+ ROW(CM_REGREF, LogLevel::llStartUp, 8, Logger::LL_INFO ),
+ ROW(FIND_NEIGHBOURS, LogLevel::llStartUp, 8, Logger::LL_INFO ),
+ ROW(NDBStopStarted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(NDBStopCompleted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(NDBStopForced, LogLevel::llStartUp, 1, Logger::LL_ALERT ),
+ ROW(NDBStopAborted, LogLevel::llStartUp, 1, Logger::LL_INFO ),
+ ROW(StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO ),
+ ROW(StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO ),
+ ROW(UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO ),
+ ROW(StartReport, LogLevel::llStartUp, 4, Logger::LL_INFO ),
+
+ // NODERESTART
+ ROW(NR_CopyDict, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyDistr, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyFragsStarted, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+ ROW(NR_CopyFragDone, LogLevel::llNodeRestart,10, Logger::LL_INFO ),
+ ROW(NR_CopyFragsCompleted, LogLevel::llNodeRestart, 8, Logger::LL_INFO ),
+
+ ROW(NodeFailCompleted, LogLevel::llNodeRestart, 8, Logger::LL_ALERT),
+ ROW(NODE_FAILREP, LogLevel::llNodeRestart, 8, Logger::LL_ALERT),
+ ROW(ArbitState, LogLevel::llNodeRestart, 6, Logger::LL_INFO ),
+ ROW(ArbitResult, LogLevel::llNodeRestart, 2, Logger::LL_ALERT),
+ ROW(GCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(GCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(LCP_TakeoverStarted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+ ROW(LCP_TakeoverCompleted, LogLevel::llNodeRestart, 7, Logger::LL_INFO ),
+
+ // STATISTIC
+ ROW(TransReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO ),
+ ROW(OperationReportCounters, LogLevel::llStatistic, 8, Logger::LL_INFO ),
+ ROW(TableCreated, LogLevel::llStatistic, 7, Logger::LL_INFO ),
+ ROW(JobStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ),
+ ROW(SendBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ),
+ ROW(ReceiveBytesStatistic, LogLevel::llStatistic, 9, Logger::LL_INFO ),
+ ROW(MemoryUsage, LogLevel::llStatistic, 5, Logger::LL_INFO ),
+
+ // ERROR
+ ROW(TransporterError, LogLevel::llError, 2, Logger::LL_ERROR ),
+ ROW(TransporterWarning, LogLevel::llError, 8, Logger::LL_WARNING ),
+ ROW(MissedHeartbeat, LogLevel::llError, 8, Logger::LL_WARNING ),
+ ROW(DeadDueToHeartbeat, LogLevel::llError, 8, Logger::LL_ALERT ),
+ ROW(WarningEvent, LogLevel::llError, 2, Logger::LL_WARNING ),
+ // INFO
+ ROW(SentHeartbeat, LogLevel::llInfo, 12, Logger::LL_INFO ),
+ ROW(CreateLogBytes, LogLevel::llInfo, 11, Logger::LL_INFO ),
+ ROW(InfoEvent, LogLevel::llInfo, 2, Logger::LL_INFO ),
+
+ //Single User
+ ROW(SingleUser, LogLevel::llInfo, 7, Logger::LL_INFO ),
+
+ // Backup
+ ROW(BackupStarted, LogLevel::llBackup, 7, Logger::LL_INFO ),
+ ROW(BackupCompleted, LogLevel::llBackup, 7, Logger::LL_INFO ),
+ ROW(BackupFailedToStart, LogLevel::llBackup, 7, Logger::LL_ALERT),
+ ROW(BackupAborted, LogLevel::llBackup, 7, Logger::LL_ALERT )
+};
+
+const Uint32 EventLoggerBase::matrixSize=
+sizeof(EventLoggerBase::matrix)/sizeof(EventRepLogLevelMatrix);
+
EventLogger::EventLogger() : m_filterLevel(15)
{
setCategory("EventLogger");
@@ -903,19 +928,37 @@ int
EventLoggerBase::event_lookup(int eventType,
LogLevel::EventCategory &cat,
Uint32 &threshold,
- Logger::LoggerLevel &severity)
+ Logger::LoggerLevel &severity,
+ EventTextFunction &textF)
{
for(unsigned i = 0; i<EventLoggerBase::matrixSize; i++){
if(EventLoggerBase::matrix[i].eventType == eventType){
cat = EventLoggerBase::matrix[i].eventCategory;
threshold = EventLoggerBase::matrix[i].threshold;
severity = EventLoggerBase::matrix[i].severity;
+ textF= EventLoggerBase::matrix[i].textF;
return 0;
}
}
return 1;
}
+const char*
+EventLogger::getText(char * dst, size_t dst_len,
+ EventTextFunction textF,
+ const Uint32* theData, NodeId nodeId )
+{
+ int pos= 0;
+ if (nodeId != 0)
+ {
+ BaseString::snprintf(dst, dst_len, "Node %u: ", nodeId);
+ pos= strlen(dst);
+ }
+ if (dst_len-pos > 0)
+ textF(dst+pos,dst_len-pos,theData);
+ return dst;
+}
+
void
EventLogger::log(int eventType, const Uint32* theData, NodeId nodeId,
const LogLevel* ll)
@@ -923,52 +966,43 @@ EventLogger::log(int eventType, const Uint32* theData, NodeId nodeId,
Uint32 threshold = 0;
Logger::LoggerLevel severity = Logger::LL_WARNING;
LogLevel::EventCategory cat= LogLevel::llInvalid;
+ EventTextFunction textF;
DBUG_ENTER("EventLogger::log");
DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
- if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity))
+ if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF))
DBUG_VOID_RETURN;
Uint32 set = ll?ll->getLogLevel(cat) : m_logLevel.getLogLevel(cat);
DBUG_PRINT("info",("threshold=%d, set=%d", threshold, set));
if (ll)
DBUG_PRINT("info",("m_logLevel.getLogLevel=%d", m_logLevel.getLogLevel(cat)));
+
if (threshold <= set){
+ getText(m_text,sizeof(m_text),textF,theData,nodeId);
+
switch (severity){
case Logger::LL_ALERT:
- alert(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ alert(m_text);
break;
-
case Logger::LL_CRITICAL:
- critical(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ critical(m_text);
break;
-
case Logger::LL_WARNING:
- warning(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ warning(m_text);
break;
-
case Logger::LL_ERROR:
- error(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ error(m_text);
break;
-
case Logger::LL_INFO:
- info(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ info(m_text);
break;
-
case Logger::LL_DEBUG:
- debug(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ debug(m_text);
break;
-
default:
- info(EventLogger::getText(m_text, sizeof(m_text),
- eventType, theData, nodeId));
+ info(m_text);
break;
}
} // if (..
diff --git a/ndb/src/common/debugger/SignalLoggerManager.cpp b/ndb/src/common/debugger/SignalLoggerManager.cpp
index d642ed09a68..67e13dc805a 100644
--- a/ndb/src/common/debugger/SignalLoggerManager.cpp
+++ b/ndb/src/common/debugger/SignalLoggerManager.cpp
@@ -139,7 +139,7 @@ SignalLoggerManager::log(LogMode logMode, const char * params)
} else {
for (int i = 0; i < count; ++i){
BlockNumber number = getBlockNo(blocks[i]);
- cnt += log(SLM_ON, number-MIN_BLOCK_NO, logMode);
+ cnt += log(SLM_ON, number, logMode);
}
}
for(int i = 0; i<count; i++){
@@ -383,7 +383,7 @@ SignalLoggerManager::sendSignalWithDelay(Uint32 delayInMilliSeconds,
* Generic messages in the signal log
*/
void
-SignalLoggerManager::log(BlockNumber bno, const char * msg)
+SignalLoggerManager::log(BlockNumber bno, const char * msg, ...)
{
// Normalise blocknumber for use in logModes array
const BlockNumber bno2 = bno - MIN_BLOCK_NO;
@@ -391,7 +391,12 @@ SignalLoggerManager::log(BlockNumber bno, const char * msg)
if(outputStream != 0 &&
logModes[bno2] != LogOff){
- fprintf(outputStream, "%s: %s\n", getBlockName(bno, "API"), msg);
+ va_list ap;
+ va_start(ap, msg);
+ fprintf(outputStream, "%s: ", getBlockName(bno, "API"));
+ vfprintf(outputStream, msg, ap);
+ fprintf(outputStream, "\n");
+ va_end(ap);
}
}
diff --git a/ndb/src/common/debugger/signaldata/BackupImpl.cpp b/ndb/src/common/debugger/signaldata/BackupImpl.cpp
index e9b0188d93b..855db0834bc 100644
--- a/ndb/src/common/debugger/signaldata/BackupImpl.cpp
+++ b/ndb/src/common/debugger/signaldata/BackupImpl.cpp
@@ -100,8 +100,10 @@ printBACKUP_FRAGMENT_CONF(FILE * out, const Uint32 * data, Uint32 l, Uint16 b){
BackupFragmentConf* sig = (BackupFragmentConf*)data;
fprintf(out, " backupPtr: %d backupId: %d\n",
sig->backupPtr, sig->backupId);
- fprintf(out, " tableId: %d fragmentNo: %d records: %d bytes: %d\n",
- sig->tableId, sig->fragmentNo, sig->noOfRecords, sig->noOfBytes);
+ fprintf(out, " tableId: %d fragmentNo: %d records: %llu bytes: %llu\n",
+ sig->tableId, sig->fragmentNo,
+ sig->noOfRecordsLow + (((Uint64)sig->noOfRecordsHigh) << 32),
+ sig->noOfBytesLow + (((Uint64)sig->noOfBytesHigh) << 32));
return true;
}
diff --git a/ndb/src/common/debugger/signaldata/BackupSignalData.cpp b/ndb/src/common/debugger/signaldata/BackupSignalData.cpp
index 4b0a0e07b66..27fed22ac72 100644
--- a/ndb/src/common/debugger/signaldata/BackupSignalData.cpp
+++ b/ndb/src/common/debugger/signaldata/BackupSignalData.cpp
@@ -72,11 +72,11 @@ printBACKUP_ABORT_REP(FILE * out, const Uint32 * data, Uint32 len, Uint16 bno){
bool
printBACKUP_COMPLETE_REP(FILE * out, const Uint32 * data, Uint32 len, Uint16 b){
BackupCompleteRep* sig = (BackupCompleteRep*)data;
- fprintf(out, " senderData: %d backupId: %d records: %d bytes: %d\n",
+ fprintf(out, " senderData: %d backupId: %d records: %llu bytes: %llu\n",
sig->senderData,
sig->backupId,
- sig->noOfRecords,
- sig->noOfBytes);
+ sig->noOfRecordsLow + (((Uint64)sig->noOfRecordsHigh) << 32),
+ sig->noOfBytesLow + (((Uint64)sig->noOfBytesHigh) << 32));
return true;
}
diff --git a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
index c6165532ddb..a1d8d82474d 100644
--- a/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
+++ b/ndb/src/common/debugger/signaldata/DictTabInfo.cpp
@@ -23,7 +23,6 @@ SimpleProperties::SP2StructMapping
DictTabInfo::TableMapping[] = {
DTIMAPS(Table, TableName, TableName, 0, MAX_TAB_NAME_SIZE),
DTIMAP(Table, TableId, TableId),
- DTIMAP(Table, SecondTableId, SecondTableId),
DTIMAPS(Table, PrimaryTable, PrimaryTable, 0, MAX_TAB_NAME_SIZE),
DTIMAP(Table, PrimaryTableId, PrimaryTableId),
DTIMAP2(Table, TableLoggedFlag, TableLoggedFlag, 0, 1),
@@ -32,8 +31,6 @@ DictTabInfo::TableMapping[] = {
DTIMAP2(Table, MaxLoadFactor, MaxLoadFactor, 25, 110),
DTIMAP2(Table, FragmentTypeVal, FragmentType, 0, 3),
DTIMAP2(Table, TableStorageVal, TableStorage, 0, 0),
- DTIMAP2(Table, ScanOptimised, ScanOptimised, 0, 0),
- DTIMAP2(Table, FragmentKeyTypeVal, FragmentKeyType, 0, 2),
DTIMAP2(Table, TableTypeVal, TableType, 1, 3),
DTIMAP(Table, NoOfKeyAttr, NoOfKeyAttr),
DTIMAP2(Table, NoOfAttributes, NoOfAttributes, 1, MAX_ATTRIBUTES_IN_TABLE),
@@ -49,6 +46,12 @@ DictTabInfo::TableMapping[] = {
DTIMAP2(Table, FrmLen, FrmLen, 0, MAX_FRM_DATA_SIZE),
DTIMAPB(Table, FrmData, FrmData, 0, MAX_FRM_DATA_SIZE, FrmLen),
DTIMAP(Table, FragmentCount, FragmentCount),
+ DTIMAP2(Table, FragmentDataLen, FragmentDataLen, 0, MAX_FRAGMENT_DATA_BYTES),
+ DTIMAPB(Table, FragmentData, FragmentData, 0, MAX_FRAGMENT_DATA_BYTES, FragmentDataLen),
+ DTIMAP(Table, MaxRowsLow, MaxRowsLow),
+ DTIMAP(Table, MaxRowsHigh, MaxRowsHigh),
+ DTIMAP(Table, MinRowsLow, MinRowsLow),
+ DTIMAP(Table, MinRowsHigh, MinRowsHigh),
DTIBREAK(AttributeName)
};
@@ -62,16 +65,12 @@ SimpleProperties::SP2StructMapping
DictTabInfo::AttributeMapping[] = {
DTIMAPS(Attribute, AttributeName, AttributeName, 0, MAX_ATTR_NAME_SIZE),
DTIMAP(Attribute, AttributeId, AttributeId),
- DTIMAP2(Attribute, AttributeType, AttributeType, 0, 3),
+ DTIMAP(Attribute, AttributeType, AttributeType),
DTIMAP2(Attribute, AttributeSize, AttributeSize, 3, 7),
DTIMAP2(Attribute, AttributeArraySize, AttributeArraySize, 0, 65535),
DTIMAP2(Attribute, AttributeKeyFlag, AttributeKeyFlag, 0, 1),
- DTIMAP2(Attribute, AttributeStorage, AttributeStorage, 0, 0),
DTIMAP2(Attribute, AttributeNullableFlag, AttributeNullableFlag, 0, 1),
- DTIMAP2(Attribute, AttributeDGroup, AttributeDGroup, 0, 1),
DTIMAP2(Attribute, AttributeDKey, AttributeDKey, 0, 1),
- DTIMAP2(Attribute, AttributeStoredInd, AttributeStoredInd, 0, 1),
- DTIMAP2(Attribute, AttributeGroup, AttributeGroup, 0, 0),
DTIMAP(Attribute, AttributeExtType, AttributeExtType),
DTIMAP(Attribute, AttributeExtPrecision, AttributeExtPrecision),
DTIMAP(Attribute, AttributeExtScale, AttributeExtScale),
@@ -104,7 +103,6 @@ void
DictTabInfo::Table::init(){
memset(TableName, 0, sizeof(TableName));//TableName[0] = 0;
TableId = ~0;
- SecondTableId = ~0;
memset(PrimaryTable, 0, sizeof(PrimaryTable));//PrimaryTable[0] = 0; // Only used when "index"
PrimaryTableId = RNIL;
TableLoggedFlag = 1;
@@ -118,8 +116,6 @@ DictTabInfo::Table::init(){
KeyLength = 0;
FragmentType = DictTabInfo::AllNodesSmallTable;
TableStorage = 0;
- ScanOptimised = 0;
- FragmentKeyType = DictTabInfo::PrimaryKey;
TableType = DictTabInfo::UndefTableType;
TableVersion = 0;
IndexState = ~0;
@@ -130,23 +126,25 @@ DictTabInfo::Table::init(){
FrmLen = 0;
memset(FrmData, 0, sizeof(FrmData));
FragmentCount = 0;
+ FragmentDataLen = 0;
+ memset(FragmentData, 0, sizeof(FragmentData));
+ MaxRowsLow = 0;
+ MaxRowsHigh = 0;
+ MinRowsLow = 0;
+ MinRowsHigh = 0;
}
void
DictTabInfo::Attribute::init(){
memset(AttributeName, 0, sizeof(AttributeName));//AttributeName[0] = 0;
AttributeId = 0;
- AttributeType = DictTabInfo::UnSignedType;
+ AttributeType = ~0, // deprecated
AttributeSize = DictTabInfo::a32Bit;
AttributeArraySize = 1;
AttributeKeyFlag = 0;
- AttributeStorage = 1;
AttributeNullableFlag = 0;
- AttributeDGroup = 0;
AttributeDKey = 0;
- AttributeStoredInd = 1;
- AttributeGroup = 0;
- AttributeExtType = 0,
+ AttributeExtType = DictTabInfo::ExtUnsigned,
AttributeExtPrecision = 0,
AttributeExtScale = 0,
AttributeExtLength = 0,
diff --git a/ndb/src/common/debugger/signaldata/FsRef.cpp b/ndb/src/common/debugger/signaldata/FsRef.cpp
index ccf3d6da9c8..ff659208d20 100644
--- a/ndb/src/common/debugger/signaldata/FsRef.cpp
+++ b/ndb/src/common/debugger/signaldata/FsRef.cpp
@@ -30,42 +30,13 @@ printFSREF(FILE * output, const Uint32 * theData,
sig->userPointer);
fprintf(output, " ErrorCode: %d, ", sig->errorCode);
+ ndbd_exit_classification cl;
switch (sig->getErrorCode(sig->errorCode)){
case FsRef::fsErrNone:
fprintf(output, "No error");
break;
- case FsRef::fsErrHardwareFailed:
- fprintf(output, "Hardware failure!");
- break;
- case FsRef::fsErrUserError:
- fprintf(output, "User error!");
- break;
- case FsRef::fsErrEnvironmentError:
- fprintf(output, "Environment error!");
- break;
- case FsRef::fsErrTemporaryNotAccessible:
- fprintf(output, "Temporary not accesible!");
- break;
- case FsRef::fsErrNoSpaceLeftOnDevice:
- fprintf(output, "No space left on device!");
- break;
- case FsRef::fsErrPermissionDenied:
- fprintf(output, "Permission denied!");
- break;
- case FsRef::fsErrInvalidParameters:
- fprintf(output, "Invalid parameters!");
- break;
- case FsRef::fsErrNoMoreResources:
- fprintf(output, "No more resources!");
- break;
- case FsRef::fsErrFileDoesNotExist:
- fprintf(output, "File does not exist!");
- break;
-
- case FsRef::fsErrUnknown:
default:
- fprintf(output, "Unknown!");
- ret = false;
+ fprintf(output, ndbd_exit_message(sig->getErrorCode(sig->errorCode), &cl));
break;
}
fprintf(output, "\n");
diff --git a/ndb/src/common/debugger/signaldata/LqhFrag.cpp b/ndb/src/common/debugger/signaldata/LqhFrag.cpp
index 6d727959a67..3175582c3a2 100644
--- a/ndb/src/common/debugger/signaldata/LqhFrag.cpp
+++ b/ndb/src/common/debugger/signaldata/LqhFrag.cpp
@@ -37,8 +37,10 @@ printLQH_FRAG_REQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 recB
fprintf(output, " noOfAttributes: %d noOfNullAttributes: %d keyLength: %d\n",
sig->noOfAttributes, sig->noOfNullAttributes, sig->keyLength);
- fprintf(output, " noOfPagesToPreAllocate: %d schemaVersion: %d nextLCP: %d\n",
- sig->noOfPagesToPreAllocate, sig->schemaVersion, sig->nextLCP);
+ fprintf(output, " maxRowsLow/High: %u/%u minRowsLow/High: %u/%u\n",
+ sig->maxRowsLow, sig->maxRowsHigh, sig->minRowsLow, sig->minRowsHigh);
+ fprintf(output, " schemaVersion: %d nextLCP: %d\n",
+ sig->schemaVersion, sig->nextLCP);
return true;
}
diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp
index 0755ee0a856..d78beb4740a 100644
--- a/ndb/src/common/debugger/signaldata/ScanTab.cpp
+++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp
@@ -30,20 +30,26 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
fprintf(output, " apiConnectPtr: H\'%.8x",
sig->apiConnectPtr);
fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo);
- fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Keyinfo: %u Holdlock: %u, RangeScan: %u ReadCommitted: %u\n",
+ fprintf(output, " Parallellism: %u Batch: %u LockMode: %u Keyinfo: %u Holdlock: %u RangeScan: %u Descending: %u TupScan: %u\n ReadCommitted: %u DistributionKeyFlag: %u",
sig->getParallelism(requestInfo),
sig->getScanBatch(requestInfo),
sig->getLockMode(requestInfo),
sig->getKeyinfoFlag(requestInfo),
sig->getHoldLockFlag(requestInfo),
sig->getRangeScanFlag(requestInfo),
- sig->getReadCommittedFlag(requestInfo));
+ sig->getDescendingFlag(requestInfo),
+ sig->getTupScanFlag(requestInfo),
+ sig->getReadCommittedFlag(requestInfo),
+ sig->getDistributionKeyFlag(requestInfo));
+
+ if(sig->getDistributionKeyFlag(requestInfo))
+ fprintf(output, " DKey: %x", sig->distributionKey);
Uint32 keyLen = (sig->attrLenKeyLen >> 16);
Uint32 attrLen = (sig->attrLenKeyLen & 0xFFFF);
fprintf(output, " attrLen: %d, keyLen: %d tableId: %d, tableSchemaVer: %d\n",
attrLen, keyLen, sig->tableId, sig->tableSchemaVersion);
-
+
fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x) storedProcId: H\'%.8x\n",
sig->transId1, sig->transId2, sig->storedProcId);
fprintf(output, " batch_byte_size: %d, first_batch_size: %d\n",
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index bd1dff074f9..572d8f6e3ca 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -27,6 +27,7 @@
const NameFunctionPair
SignalDataPrintFunctions[] = {
{ GSN_TCKEYREQ, printTCKEYREQ },
+ { GSN_TCINDXREQ, printTCKEYREQ },
{ GSN_TCKEYCONF, printTCKEYCONF },
{ GSN_TCKEYREF, printTCKEYREF },
{ GSN_LQHKEYREQ, printLQHKEYREQ },
@@ -82,14 +83,10 @@ SignalDataPrintFunctions[] = {
{ GSN_ALTER_INDX_REQ, printALTER_INDX_REQ },
{ GSN_ALTER_INDX_CONF, printALTER_INDX_CONF },
{ GSN_ALTER_INDX_REF, printALTER_INDX_REF },
- { GSN_TCINDXREQ, printTCINDXREQ },
{ GSN_TCINDXCONF, printTCINDXCONF },
{ GSN_TCINDXREF, printTCINDXREF },
{ GSN_INDXKEYINFO, printINDXKEYINFO },
{ GSN_INDXATTRINFO, printINDXATTRINFO },
- //{ GSN_TCINDXNEXTREQ, printTCINDXNEXTREQ },
- //{ GSN_TCINDEXNEXTCONF, printTCINDEXNEXTCONF },
- //{ GSN_TCINDEXNEXREF, printTCINDEXNEXREF },
{ GSN_FSAPPENDREQ, printFSAPPENDREQ },
{ GSN_BACKUP_REQ, printBACKUP_REQ },
{ GSN_BACKUP_DATA, printBACKUP_DATA },
@@ -154,11 +151,11 @@ SignalDataPrintFunctions[] = {
{ GSN_DISCONNECT_REP, printDISCONNECT_REP },
{ GSN_SUB_CREATE_REQ, printSUB_CREATE_REQ },
- //{ GSN_SUB_CREATE_REF, printSUB_CREATE_REF },
+ { GSN_SUB_CREATE_REF, printSUB_CREATE_REF },
{ GSN_SUB_CREATE_CONF, printSUB_CREATE_CONF },
- { GSN_SUB_START_REQ, printSUB_START_REQ },
- { GSN_SUB_START_REF, printSUB_START_REF },
- { GSN_SUB_START_CONF, printSUB_START_CONF },
+ { GSN_SUB_REMOVE_REQ, printSUB_REMOVE_REQ },
+ { GSN_SUB_REMOVE_REF, printSUB_REMOVE_REF },
+ { GSN_SUB_REMOVE_CONF, printSUB_REMOVE_CONF },
{ GSN_SUB_SYNC_REQ, printSUB_SYNC_REQ },
{ GSN_SUB_SYNC_REF, printSUB_SYNC_REF },
{ GSN_SUB_SYNC_CONF, printSUB_SYNC_CONF },
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 9228e305677..49e3f505b11 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -399,6 +399,8 @@ const GsnName SignalNames [] = {
,{ GSN_TUP_COM_UNBLOCK, "TUP_COM_UNBLOCK" }
,{ GSN_DUMP_STATE_ORD, "DUMP_STATE_ORD" }
+ ,{ GSN_NODE_START_REP, "NODE_START_REP" }
+
,{ GSN_START_INFOREQ, "START_INFOREQ" }
,{ GSN_START_INFOREF, "START_INFOREF" }
,{ GSN_START_INFOCONF, "START_INFOCONF" }
@@ -502,18 +504,6 @@ const GsnName SignalNames [] = {
//,{ GSN_TCINDEXNEXTCONF, "TCINDEXNEXTCONF" }
//,{ GSN_TCINDEXNEXREF, "TCINDEXNEXREF" }
- ,{ GSN_CREATE_EVNT_REQ, "CREATE_EVNT_REQ" }
- ,{ GSN_CREATE_EVNT_CONF, "CREATE_EVNT_CONF" }
- ,{ GSN_CREATE_EVNT_REF, "CREATE_EVNT_REF" }
-
- ,{ GSN_SUMA_START_ME, "SUMA_START_ME" }
- ,{ GSN_SUMA_HANDOVER_REQ, "SUMA_HANDOVER_REQ"}
- ,{ GSN_SUMA_HANDOVER_CONF, "SUMA_HANDOVER_CONF"}
-
- ,{ GSN_DROP_EVNT_REQ, "DROP_EVNT_REQ" }
- ,{ GSN_DROP_EVNT_CONF, "DROP_EVNT_CONF" }
- ,{ GSN_DROP_EVNT_REF, "DROP_EVNT_REF" }
-
,{ GSN_BACKUP_TRIG_REQ, "BACKUP_TRIG_REQ" }
,{ GSN_BACKUP_REQ, "BACKUP_REQ" }
,{ GSN_BACKUP_DATA, "BACKUP_DATA" }
@@ -578,12 +568,9 @@ const GsnName SignalNames [] = {
,{ GSN_SUB_CREATE_REQ, "SUB_CREATE_REQ" }
,{ GSN_SUB_CREATE_REF, "SUB_CREATE_REF" }
,{ GSN_SUB_CREATE_CONF, "SUB_CREATE_CONF" }
- ,{ GSN_SUB_START_REQ, "SUB_START_REQ" }
- ,{ GSN_SUB_START_REF, "SUB_START_REF" }
- ,{ GSN_SUB_START_CONF, "SUB_START_CONF" }
- ,{ GSN_SUB_STOP_REQ, "SUB_STOP_REQ" }
- ,{ GSN_SUB_STOP_REF, "SUB_STOP_REF" }
- ,{ GSN_SUB_STOP_CONF, "SUB_STOP_CONF" }
+ ,{ GSN_SUB_REMOVE_REQ, "SUB_REMOVE_REQ" }
+ ,{ GSN_SUB_REMOVE_REF, "SUB_REMOVE_REF" }
+ ,{ GSN_SUB_REMOVE_CONF, "SUB_REMOVE_CONF" }
,{ GSN_SUB_SYNC_REQ, "SUB_SYNC_REQ" }
,{ GSN_SUB_SYNC_REF, "SUB_SYNC_REF" }
,{ GSN_SUB_SYNC_CONF, "SUB_SYNC_CONF" }
@@ -593,7 +580,6 @@ const GsnName SignalNames [] = {
,{ GSN_SUB_SYNC_CONTINUE_REF, "SUB_SYNC_CONTINUE_REF" }
,{ GSN_SUB_SYNC_CONTINUE_CONF, "SUB_SYNC_CONTINUE_CONF" }
,{ GSN_SUB_GCP_COMPLETE_REP, "SUB_GCP_COMPLETE_REP" }
- ,{ GSN_SUB_GCP_COMPLETE_ACC, "SUB_GCP_COMPLETE_ACC" }
,{ GSN_CREATE_SUBID_REQ, "CREATE_SUBID_REQ" }
,{ GSN_CREATE_SUBID_REF, "CREATE_SUBID_REF" }
@@ -644,6 +630,12 @@ const GsnName SignalNames [] = {
,{ GSN_TUX_MAINT_REF, "TUX_MAINT_REF" }
,{ GSN_TUX_BOUND_INFO, "TUX_BOUND_INFO" }
,{ GSN_ACC_LOCKREQ, "ACC_LOCKREQ" }
+
+ /* DICT LOCK */
+ ,{ GSN_DICT_LOCK_REQ, "DICT_LOCK_REQ" }
+ ,{ GSN_DICT_LOCK_CONF, "DICT_LOCK_CONF" }
+ ,{ GSN_DICT_LOCK_REF, "DICT_LOCK_REF" }
+ ,{ GSN_DICT_UNLOCK_ORD, "DICT_UNLOCK_ORD" }
};
const unsigned short NO_OF_SIGNAL_NAMES = sizeof(SignalNames)/sizeof(GsnName);
diff --git a/ndb/src/common/debugger/signaldata/SumaImpl.cpp b/ndb/src/common/debugger/signaldata/SumaImpl.cpp
index 558842ed2ba..e50a3040fe3 100644
--- a/ndb/src/common/debugger/signaldata/SumaImpl.cpp
+++ b/ndb/src/common/debugger/signaldata/SumaImpl.cpp
@@ -40,12 +40,55 @@ printSUB_CREATE_CONF(FILE * output, const Uint32 * theData,
}
bool
+printSUB_CREATE_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubCreateRef * const sig = (SubCreateRef *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
+printSUB_REMOVE_REQ(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo)
+{
+ const SubRemoveReq * const sig = (SubRemoveReq *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ return false;
+}
+
+bool
+printSUB_REMOVE_CONF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo)
+{
+ const SubRemoveConf * const sig = (SubRemoveConf *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
+printSUB_REMOVE_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo)
+{
+ const SubRemoveRef * const sig = (SubRemoveRef *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ fprintf(output, " err: %x\n", sig->err);
+ return false;
+}
+
+bool
printSUB_START_REQ(FILE * output, const Uint32 * theData,
Uint32 len, Uint16 receiverBlockNo) {
const SubStartReq * const sig = (SubStartReq *)theData;
fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
- fprintf(output, " startPart: %x\n", sig->part);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
return false;
}
@@ -73,6 +116,37 @@ printSUB_START_CONF(FILE * output, const Uint32 * theData,
}
bool
+printSUB_STOP_REQ(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubStopReq * const sig = (SubStopReq *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
+printSUB_STOP_REF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubStopRef * const sig = (SubStopRef *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ fprintf(output, " err: %x\n", sig->err);
+ return false;
+}
+
+bool
+printSUB_STOP_CONF(FILE * output, const Uint32 * theData,
+ Uint32 len, Uint16 receiverBlockNo) {
+ const SubStopConf * const sig = (SubStopConf *)theData;
+ fprintf(output, " subscriptionId: %x\n", sig->subscriptionId);
+ fprintf(output, " subscriptionKey: %x\n", sig->subscriptionKey);
+ fprintf(output, " subscriberData: %x\n", sig->subscriberData);
+ return false;
+}
+
+bool
printSUB_SYNC_REQ(FILE * output, const Uint32 * theData,
Uint32 len, Uint16 receiverBlockNo) {
const SubSyncReq * const sig = (SubSyncReq *)theData;
diff --git a/ndb/src/common/debugger/signaldata/TcIndx.cpp b/ndb/src/common/debugger/signaldata/TcIndx.cpp
index 6bfa29eff15..b0578f5b646 100644
--- a/ndb/src/common/debugger/signaldata/TcIndx.cpp
+++ b/ndb/src/common/debugger/signaldata/TcIndx.cpp
@@ -18,91 +18,6 @@
#include <signaldata/TcKeyReq.hpp>
#include <BlockNumbers.h>
-bool
-printTCINDXREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
-
- const TcIndxReq * const sig = (TcIndxReq *) theData;
-
- UintR requestInfo = sig->requestInfo;
- UintR scanInfo = sig->scanInfo;
-
- fprintf(output, " apiConnectPtr: H\'%.8x, senderData: H\'%.8x\n",
- sig->apiConnectPtr, sig->senderData);
-
- fprintf(output, " Operation: %s, Flags: ",
- sig->getOperationType(requestInfo) == ZREAD ? "Read" :
- sig->getOperationType(requestInfo) == ZREAD_EX ? "Read-Ex" :
- sig->getOperationType(requestInfo) == ZUPDATE ? "Update" :
- sig->getOperationType(requestInfo) == ZINSERT ? "Insert" :
- sig->getOperationType(requestInfo) == ZDELETE ? "Delete" :
- sig->getOperationType(requestInfo) == ZWRITE ? "Write" :
- "Unknown");
-
- {
- if(sig->getDirtyFlag(requestInfo)){
- fprintf(output, "Dirty ");
- }
- if(sig->getStartFlag(requestInfo)){
- fprintf(output, "Start ");
- }
- if (TcKeyReq::getExecuteFlag(sig->requestInfo)) {
- fprintf(output, "Execute ");
- }
- if(sig->getCommitFlag(requestInfo)){
- fprintf(output, "Commit, Type = ");
- UintR TcommitType = sig->getCommitType(requestInfo);
- if (TcommitType == TcIndxReq::CommitIfFailFree) {
- fprintf(output, "FailFree ");
- } else if (TcommitType == TcIndxReq::TryCommit) {
- fprintf(output, "TryCommit ");
- } else if (TcommitType == TcIndxReq::CommitAsMuchAsPossible) {
- fprintf(output, "Always ");
- }//if
- }
- if(sig->getSimpleFlag(requestInfo)){
- fprintf(output, "Simple ");
- }
- if(sig->getInterpretedFlag(requestInfo)){
- fprintf(output, "Interpreted ");
- }
- if(sig->getDistributionGroupFlag(requestInfo)){
- fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
- }
- if(sig->getDistributionKeyFlag(sig->requestInfo)){
- fprintf(output, "DKey = %d ", sig->distributionKeySize);
- }
- fprintf(output, "\n");
- }
-
- const int indexLen = sig->getIndexLength(requestInfo);
- const int attrInThis = sig->getAIInTcIndxReq(requestInfo);
- fprintf(output,
- " indexLen: %d, attrLen: %d, AI in this: %d, indexId: %d, "
- "indexSchemaVer: %d, API Ver: %d\n",
- indexLen, sig->attrLen, attrInThis,
- sig->indexId, sig->indexSchemaVersion, sig->getAPIVersion(scanInfo));
-
- fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n -- Variable Data --\n",
- sig->transId1, sig->transId2);
-
- Uint32 restLen = (len - 8);
- const Uint32 * rest = &sig->scanInfo;
- 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 true;
-}
bool
printTCINDXCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
diff --git a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
index 7304872ff9c..3918bd5db26 100644
--- a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
+++ b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
@@ -68,11 +68,8 @@ printTCKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiver
if(sig->getInterpretedFlag(requestInfo)){
fprintf(output, "Interpreted ");
}
- if(sig->getDistributionGroupFlag(requestInfo)){
- fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
- }
if(sig->getDistributionKeyFlag(sig->requestInfo)){
- fprintf(output, "DKey = %d ", sig->distributionKeySize);
+ fprintf(output, " d-key");
}
fprintf(output, "\n");
}
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index b870bc67aa3..c2b3e8235eb 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -52,6 +52,7 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string,
m_version = version;
m_node_type = node_type;
_ownNodeId= 0;
+ m_end_session= true;
m_handle= ndb_mgm_create_handle();
@@ -73,6 +74,8 @@ ConfigRetriever::~ConfigRetriever()
{
DBUG_ENTER("ConfigRetriever::~ConfigRetriever");
if (m_handle) {
+ if(m_end_session)
+ ndb_mgm_end_session(m_handle);
ndb_mgm_disconnect(m_handle);
ndb_mgm_destroy_handle(&m_handle);
}
@@ -112,6 +115,12 @@ ConfigRetriever::do_connect(int no_retries,
0 : -1;
}
+int
+ConfigRetriever::disconnect()
+{
+ return ndb_mgm_disconnect(m_handle);
+}
+
//****************************************************************************
//****************************************************************************
//****************************************************************************
@@ -330,15 +339,24 @@ ConfigRetriever::setNodeId(Uint32 nodeid)
Uint32
ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds)
{
+ int res;
_ownNodeId= 0;
if(m_handle != 0)
{
while (1)
{
- int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type);
+ if(!ndb_mgm_is_connected(m_handle))
+ if(!ndb_mgm_connect(m_handle, 0, 0, 0))
+ goto next;
+
+ res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type,
+ no_retries == 0 /* only log last retry */);
if(res >= 0)
return _ownNodeId= (Uint32)res;
- if (no_retries == 0)
+
+ next:
+ int error = ndb_mgm_get_latest_error(m_handle);
+ if (no_retries == 0 || error == NDB_MGM_ALLOCID_CONFIG_MISMATCH)
break;
no_retries--;
NdbSleep_SecSleep(retry_delay_in_seconds);
diff --git a/ndb/src/common/mgmcommon/IPCConfig.cpp b/ndb/src/common/mgmcommon/IPCConfig.cpp
index 8cf5e6e8d45..bc442ffc3ef 100644
--- a/ndb/src/common/mgmcommon/IPCConfig.cpp
+++ b/ndb/src/common/mgmcommon/IPCConfig.cpp
@@ -111,178 +111,6 @@ IPCConfig::addRemoteNodeId(NodeId nodeId){
}
/**
- * Returns no of transporters configured
- */
-int
-IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry)
-{
- DBUG_ENTER("IPCConfig::configureTransporters");
-
- int noOfTransportersCreated = 0;
-
- Uint32 noOfConnections;
- if(!props->get("NoOfConnections", &noOfConnections)) return -1;
-
- for (Uint32 i = 0; i < noOfConnections; i++){
- const Properties * tmp;
- Uint32 nodeId1, nodeId2;
- const char * host1;
- const char * host2;
-
- if(!props->get("Connection", i, &tmp)) continue;
- if(!tmp->get("NodeId1", &nodeId1)) continue;
- if(!tmp->get("NodeId2", &nodeId2)) continue;
- if(nodeId1 != the_ownId && nodeId2 != the_ownId) continue;
-
- Uint32 sendSignalId;
- Uint32 compression;
- Uint32 checksum;
- if(!tmp->get("SendSignalId", &sendSignalId)) continue;
- if(!tmp->get("Checksum", &checksum)) continue;
-
- const char * type;
- if(!tmp->get("Type", &type)) continue;
-
- if(strcmp("SHM", type) == 0){
- SHM_TransporterConfiguration conf;
- conf.localNodeId = the_ownId;
- conf.remoteNodeId = (nodeId1 != the_ownId ? nodeId1 : nodeId2);
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!tmp->get("ShmKey", &conf.shmKey)) continue;
- if(!tmp->get("ShmSize", &conf.shmSize)) continue;
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create SHM Transporter from: "
- << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
- continue;
- } else {
- noOfTransportersCreated++;
- continue;
- }
-
- } else if(strcmp("SCI", type) == 0){
- SCI_TransporterConfiguration conf;
- conf.localNodeId = the_ownId;
- conf.remoteNodeId = (nodeId1 != the_ownId ? nodeId1 : nodeId2);
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!tmp->get("SendLimit", &conf.sendLimit)) continue;
- if(!tmp->get("SharedBufferSize", &conf.bufferSize)) continue;
-
- if(the_ownId == nodeId1){
- if(!tmp->get("Node1_NoOfAdapters", &conf.nLocalAdapters)) continue;
- if(!tmp->get("Node2_Adapter", 0, &conf.remoteSciNodeId0)) continue;
-
- if(conf.nLocalAdapters > 1){
- if(!tmp->get("Node2_Adapter", 1, &conf.remoteSciNodeId1)) continue;
- }
- } else {
- if(!tmp->get("Node2_NoOfAdapters", &conf.nLocalAdapters)) continue;
- if(!tmp->get("Node1_Adapter", 0, &conf.remoteSciNodeId0)) continue;
-
- if(conf.nLocalAdapters > 1){
- if(!tmp->get("Node1_Adapter", 1, &conf.remoteSciNodeId1)) continue;
- }
- }
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create SCI Transporter from: "
- << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
- continue;
- } else {
- noOfTransportersCreated++;
- continue;
- }
- }
-
- if(!tmp->get("HostName1", &host1)) continue;
- if(!tmp->get("HostName2", &host2)) continue;
-
- Uint32 ownNodeId;
- Uint32 remoteNodeId;
- const char * ownHostName;
- const char * remoteHostName;
-
- if(nodeId1 == the_ownId){
- ownNodeId = nodeId1;
- ownHostName = host1;
- remoteNodeId = nodeId2;
- remoteHostName = host2;
- } else if(nodeId2 == the_ownId){
- ownNodeId = nodeId2;
- ownHostName = host2;
- remoteNodeId = nodeId1;
- remoteHostName = host1;
- } else {
- continue;
- }
-
- if(strcmp("TCP", type) == 0){
- TCP_TransporterConfiguration conf;
-
- if(!tmp->get("PortNumber", &conf.port)) continue;
- if(!tmp->get("SendBufferSize", &conf.sendBufferSize)) continue;
- if(!tmp->get("MaxReceiveSize", &conf.maxReceiveSize)) continue;
-
- const char * proxy;
- if (tmp->get("Proxy", &proxy)) {
- if (strlen(proxy) > 0 && nodeId2 == the_ownId) {
- // TODO handle host:port
- conf.port = atoi(proxy);
- }
- }
- conf.sendBufferSize *= MAX_MESSAGE_SIZE;
- conf.maxReceiveSize *= MAX_MESSAGE_SIZE;
-
- conf.remoteHostName = remoteHostName;
- conf.localHostName = ownHostName;
- conf.remoteNodeId = remoteNodeId;
- conf.localNodeId = ownNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create TCP Transporter from: "
- << ownNodeId << " to: " << remoteNodeId << endl;
- } else {
- noOfTransportersCreated++;
- }
-
- } else if(strcmp("OSE", type) == 0){
-
- OSE_TransporterConfiguration conf;
-
- if(!tmp->get("PrioASignalSize", &conf.prioASignalSize))
- continue;
- if(!tmp->get("PrioBSignalSize", &conf.prioBSignalSize))
- continue;
- if(!tmp->get("ReceiveArraySize", &conf.receiveBufferSize))
- continue;
-
- conf.remoteHostName = remoteHostName;
- conf.localHostName = ownHostName;
- conf.remoteNodeId = remoteNodeId;
- conf.localNodeId = ownNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!theTransporterRegistry->createTransporter(&conf)){
- ndbout << "Failed to create OSE Transporter from: "
- << ownNodeId << " to: " << remoteNodeId << endl;
- } else {
- noOfTransportersCreated++;
- }
- } else {
- continue;
- }
- }
- DBUG_RETURN(noOfTransportersCreated);
-}
-
-/**
* Supply a nodeId,
* and get next higher node id
* Returns false if none found
@@ -338,8 +166,39 @@ Uint32
IPCConfig::configureTransporters(Uint32 nodeId,
const class ndb_mgm_configuration & config,
class TransporterRegistry & tr){
+ TransporterConfiguration conf;
+
DBUG_ENTER("IPCConfig::configureTransporters");
+ /**
+ * Iterate over all MGM's an construct a connectstring
+ * create mgm_handle and give it to the Transporter Registry
+ */
+ {
+ const char *separator= "";
+ BaseString connect_string;
+ ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
+ for(iter.first(); iter.valid(); iter.next())
+ {
+ Uint32 type;
+ if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
+ if(type != NODE_TYPE_MGM) continue;
+ const char* hostname;
+ Uint32 port;
+ if(iter.get(CFG_NODE_HOST, &hostname)) continue;
+ if( strlen(hostname) == 0 ) continue;
+ if(iter.get(CFG_MGM_PORT, &port)) continue;
+ connect_string.appfmt("%s%s:%u",separator,hostname,port);
+ separator= ",";
+ }
+ NdbMgmHandle h= ndb_mgm_create_handle();
+ if ( h && connect_string.length() > 0 )
+ {
+ ndb_mgm_set_connectstring(h,connect_string.c_str());
+ tr.set_mgm_handle(h);
+ }
+ }
+
Uint32 noOfTransportersCreated= 0;
ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
@@ -371,32 +230,62 @@ IPCConfig::configureTransporters(Uint32 nodeId,
Uint32 server_port= 0;
if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;
- if (nodeId <= nodeId1 && nodeId <= nodeId2) {
- tr.add_transporter_interface(localHostName, server_port);
+
+ Uint32 nodeIdServer= 0;
+ if(iter.get(CFG_CONNECTION_NODE_ID_SERVER, &nodeIdServer)) break;
+
+ /*
+ We check the node type.
+ */
+ Uint32 node1type, node2type;
+ ndb_mgm_configuration_iterator node1iter(config, CFG_SECTION_NODE);
+ ndb_mgm_configuration_iterator node2iter(config, CFG_SECTION_NODE);
+ node1iter.find(CFG_NODE_ID,nodeId1);
+ node2iter.find(CFG_NODE_ID,nodeId2);
+ node1iter.get(CFG_TYPE_OF_SECTION,&node1type);
+ node2iter.get(CFG_TYPE_OF_SECTION,&node2type);
+
+ if(node1type==NODE_TYPE_MGM || node2type==NODE_TYPE_MGM)
+ conf.isMgmConnection= true;
+ else
+ conf.isMgmConnection= false;
+
+ if (nodeId == nodeIdServer && !conf.isMgmConnection) {
+ tr.add_transporter_interface(remoteNodeId, localHostName, server_port);
}
+
DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
nodeId, remoteNodeId, server_port, sendSignalId, checksum));
+ /*
+ This may be a dynamic port. It depends on when we're getting
+ our configuration. If we've been restarted, we'll be getting
+ a configuration with our old dynamic port in it, hence the number
+ here is negative (and we try the old port number first).
+
+ On a first-run, server_port will be zero (with dynamic ports)
+
+ If we're not using dynamic ports, we don't do anything.
+ */
+
+ conf.localNodeId = nodeId;
+ conf.remoteNodeId = remoteNodeId;
+ conf.checksum = checksum;
+ conf.signalId = sendSignalId;
+ conf.s_port = server_port;
+ conf.localHostName = localHostName;
+ conf.remoteHostName = remoteHostName;
+ conf.serverNodeId = nodeIdServer;
+
switch(type){
- case CONNECTION_TYPE_SHM:{
- SHM_TransporterConfiguration conf;
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(iter.get(CFG_SHM_KEY, &conf.shmKey)) break;
- if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shmSize)) break;
- {
- Uint32 tmp;
- if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
- conf.signum= tmp;
- }
+ case CONNECTION_TYPE_SHM:
+ if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
+ if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;
- conf.port= server_port;
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
+ Uint32 tmp;
+ if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
+ conf.shm.signum= tmp;
- if(!tr.createTransporter(&conf)){
+ if(!tr.createSHMTransporter(&conf)){
DBUG_PRINT("error", ("Failed to create SHM Transporter from %d to %d",
conf.localNodeId, conf.remoteNodeId));
ndbout << "Failed to create SHM Transporter from: "
@@ -404,112 +293,90 @@ IPCConfig::configureTransporters(Uint32 nodeId,
} else {
noOfTransportersCreated++;
}
- DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, buf size = %d",
- conf.shmKey, conf.shmSize));
+ DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, "
+ "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));
+
break;
- }
- case CONNECTION_TYPE_SCI:{
- SCI_TransporterConfiguration conf;
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
- conf.port= server_port;
-
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
- if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sendLimit)) break;
- if(iter.get(CFG_SCI_BUFFER_MEM, &conf.bufferSize)) break;
+ case CONNECTION_TYPE_SCI:
+ if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
+ if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
if (nodeId == nodeId1) {
- if(iter.get(CFG_SCI_HOST2_ID_0, &conf.remoteSciNodeId0)) break;
- if(iter.get(CFG_SCI_HOST2_ID_1, &conf.remoteSciNodeId1)) break;
+ if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
+ if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
} else {
- if(iter.get(CFG_SCI_HOST1_ID_0, &conf.remoteSciNodeId0)) break;
- if(iter.get(CFG_SCI_HOST1_ID_1, &conf.remoteSciNodeId1)) break;
+ if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
+ if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
}
- if (conf.remoteSciNodeId1 == 0) {
- conf.nLocalAdapters = 1;
+ if (conf.sci.remoteSciNodeId1 == 0) {
+ conf.sci.nLocalAdapters = 1;
} else {
- conf.nLocalAdapters = 2;
+ conf.sci.nLocalAdapters = 2;
}
- if(!tr.createTransporter(&conf)){
+ if(!tr.createSCITransporter(&conf)){
DBUG_PRINT("error", ("Failed to create SCI Transporter from %d to %d",
conf.localNodeId, conf.remoteNodeId));
ndbout << "Failed to create SCI Transporter from: "
<< conf.localNodeId << " to: " << conf.remoteNodeId << endl;
} else {
- DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, remote SCI node id %d",
- conf.nLocalAdapters, conf.remoteSciNodeId0));
- DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, buf size = %d",
- conf.localHostName, conf.remoteHostName, conf.sendLimit, conf.bufferSize));
- if (conf.nLocalAdapters > 1) {
- DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, second remote SCI node id = %d",
- conf.remoteSciNodeId1));
+ DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, "
+ "remote SCI node id %d",
+ conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
+ DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
+ "buf size = %d", conf.localHostName,
+ conf.remoteHostName, conf.sci.sendLimit,
+ conf.sci.bufferSize));
+ if (conf.sci.nLocalAdapters > 1) {
+ DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
+ "second remote SCI node id = %d",
+ conf.sci.remoteSciNodeId1));
}
noOfTransportersCreated++;
continue;
}
- }
- case CONNECTION_TYPE_TCP:{
- TCP_TransporterConfiguration conf;
-
- if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.sendBufferSize)) break;
- if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.maxReceiveSize)) break;
+ break;
+
+ case CONNECTION_TYPE_TCP:
+ if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
+ if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;
- conf.port= server_port;
const char * proxy;
if (!iter.get(CFG_TCP_PROXY, &proxy)) {
if (strlen(proxy) > 0 && nodeId2 == nodeId) {
// TODO handle host:port
- conf.port = atoi(proxy);
+ conf.s_port = atoi(proxy);
}
}
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
-
- if(!tr.createTransporter(&conf)){
+ if(!tr.createTCPTransporter(&conf)){
ndbout << "Failed to create TCP Transporter from: "
<< nodeId << " to: " << remoteNodeId << endl;
} else {
noOfTransportersCreated++;
}
- DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, maxReceiveSize = %d",
- conf.sendBufferSize, conf.maxReceiveSize));
+ DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, "
+ "maxReceiveSize = %d", conf.tcp.sendBufferSize,
+ conf.tcp.maxReceiveSize));
break;
- case CONNECTION_TYPE_OSE:{
- OSE_TransporterConfiguration conf;
-
- if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.prioASignalSize)) break;
- if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.prioBSignalSize)) break;
- if(iter.get(CFG_OSE_RECEIVE_ARRAY_SIZE, &conf.receiveBufferSize)) break;
-
- conf.localNodeId = nodeId;
- conf.remoteNodeId = remoteNodeId;
- conf.localHostName = localHostName;
- conf.remoteHostName = remoteHostName;
- conf.checksum = checksum;
- conf.signalId = sendSignalId;
+ case CONNECTION_TYPE_OSE:
+ if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.ose.prioASignalSize)) break;
+ if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.ose.prioBSignalSize)) break;
- if(!tr.createTransporter(&conf)){
+ if(!tr.createOSETransporter(&conf)){
ndbout << "Failed to create OSE Transporter from: "
<< nodeId << " to: " << remoteNodeId << endl;
} else {
noOfTransportersCreated++;
}
- }
+ break;
+
default:
ndbout << "Unknown transporter type from: " << nodeId <<
" to: " << remoteNodeId << endl;
break;
- }
- }
- }
+ } // switch
+ } // for
+
DBUG_RETURN(noOfTransportersCreated);
}
diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am
index 99138a7414e..1e27d713495 100644
--- a/ndb/src/common/portlib/Makefile.am
+++ b/ndb/src/common/portlib/Makefile.am
@@ -1,5 +1,3 @@
-noinst_HEADERS = gcc.cpp
-
noinst_LTLIBRARIES = libportlib.la
libportlib_la_SOURCES = \
diff --git a/ndb/src/common/portlib/NdbConfig.c b/ndb/src/common/portlib/NdbConfig.c
index b275143646f..c3f37727024 100644
--- a/ndb/src/common/portlib/NdbConfig.c
+++ b/ndb/src/common/portlib/NdbConfig.c
@@ -64,11 +64,11 @@ NdbConfig_NdbCfgName(int with_ndb_home){
int len= 0;
if (with_ndb_home) {
- buf= NdbConfig_AllocHomePath(128);
+ buf= NdbConfig_AllocHomePath(PATH_MAX);
len= strlen(buf);
} else
- buf= NdbMem_Allocate(128);
- basestring_snprintf(buf+len, 128, "Ndb.cfg");
+ buf= NdbMem_Allocate(PATH_MAX);
+ basestring_snprintf(buf+len, PATH_MAX, "Ndb.cfg");
return buf;
}
@@ -90,56 +90,56 @@ char *get_prefix_buf(int len, int node_id)
char*
NdbConfig_ErrorFileName(int node_id){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, "_error.log");
+ basestring_snprintf(buf+len, PATH_MAX, "_error.log");
return buf;
}
char*
NdbConfig_ClusterLogFileName(int node_id){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, "_cluster.log");
+ basestring_snprintf(buf+len, PATH_MAX, "_cluster.log");
return buf;
}
char*
NdbConfig_SignalLogFileName(int node_id){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, "_signal.log");
+ basestring_snprintf(buf+len, PATH_MAX, "_signal.log");
return buf;
}
char*
NdbConfig_TraceFileName(int node_id, int file_no){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, "_trace.log.%u", file_no);
+ basestring_snprintf(buf+len, PATH_MAX, "_trace.log.%u", file_no);
return buf;
}
char*
NdbConfig_NextTraceFileName(int node_id){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, "_trace.log.next");
+ basestring_snprintf(buf+len, PATH_MAX, "_trace.log.next");
return buf;
}
char*
NdbConfig_PidFileName(int node_id){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, ".pid");
+ basestring_snprintf(buf+len, PATH_MAX, ".pid");
return buf;
}
char*
NdbConfig_StdoutFileName(int node_id){
- char *buf= get_prefix_buf(128, node_id);
+ char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf);
- basestring_snprintf(buf+len, 128, "_out.log");
+ basestring_snprintf(buf+len, PATH_MAX, "_out.log");
return buf;
}
diff --git a/ndb/src/common/portlib/NdbTCP.cpp b/ndb/src/common/portlib/NdbTCP.cpp
index c7b9d33c5f6..41471548b7e 100644
--- a/ndb/src/common/portlib/NdbTCP.cpp
+++ b/ndb/src/common/portlib/NdbTCP.cpp
@@ -83,3 +83,50 @@ Ndb_getInAddr(struct in_addr * dst, const char *address) {
return -1;
}
#endif
+
+int Ndb_check_socket_hup(NDB_SOCKET_TYPE sock)
+{
+#ifdef HAVE_POLL
+ struct pollfd pfd[1];
+ int r;
+
+ pfd[0].fd= sock;
+ pfd[0].events= POLLHUP | POLLIN | POLLOUT | POLLNVAL;
+ pfd[0].revents= 0;
+ r= poll(pfd,1,0);
+ if(pfd[0].revents & (POLLHUP|POLLERR))
+ return 1;
+
+ return 0;
+#else /* HAVE_POLL */
+ fd_set readfds, writefds, errorfds;
+ struct timeval tv= {0,0};
+ int s_err;
+ int s_err_size= sizeof(s_err);
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&errorfds);
+
+ FD_SET(sock, &readfds);
+ FD_SET(sock, &writefds);
+ FD_SET(sock, &errorfds);
+
+ if(select(1, &readfds, &writefds, &errorfds, &tv)<0)
+ return 1;
+
+ if(FD_ISSET(sock,&errorfds))
+ return 1;
+
+ s_err=0;
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+ return(1);
+
+ if (s_err)
+ { /* getsockopt could succeed */
+ return(1); /* but return an error... */
+ }
+
+ return 0;
+#endif /* HAVE_POLL */
+}
diff --git a/ndb/src/common/portlib/gcc.cpp b/ndb/src/common/portlib/gcc.cpp
deleted file mode 100644
index 66aa4812dc6..00000000000
--- a/ndb/src/common/portlib/gcc.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-
-/**
- * GCC linking problem...
- */
-#ifdef DEFINE_CXA_PURE_VIRTUAL
-extern "C" { int __cxa_pure_virtual() { return 0;} }
-#endif
diff --git a/ndb/src/common/portlib/win32/NdbTCP.c b/ndb/src/common/portlib/win32/NdbTCP.c
index b936cd2db6c..5d6c0ae5c7d 100644
--- a/ndb/src/common/portlib/win32/NdbTCP.c
+++ b/ndb/src/common/portlib/win32/NdbTCP.c
@@ -37,3 +37,35 @@ Ndb_getInAddr(struct in_addr * dst, const char *address)
return -1;
}
+int Ndb_check_socket_hup(NDB_SOCKET_TYPE sock)
+{
+ fd_set readfds, writefds, errorfds;
+ struct timeval tv= {0,0};
+ int s_err;
+ int s_err_size= sizeof(s_err);
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&errorfds);
+
+ FD_SET(sock, &readfds);
+ FD_SET(sock, &writefds);
+ FD_SET(sock, &errorfds);
+
+ if(select(1, &readfds, &writefds, &errorfds, &tv)==SOCKET_ERROR)
+ return 1;
+
+ if(FD_ISSET(sock,&errorfds))
+ return 1;
+
+ s_err=0;
+ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
+ return(1);
+
+ if (s_err)
+ { /* getsockopt could succeed */
+ return(1); /* but return an error... */
+ }
+
+ return 0;
+}
diff --git a/ndb/src/common/transporter/Makefile.am b/ndb/src/common/transporter/Makefile.am
index b902012e56d..4c277097a91 100644
--- a/ndb/src/common/transporter/Makefile.am
+++ b/ndb/src/common/transporter/Makefile.am
@@ -13,7 +13,7 @@ EXTRA_libtransporter_la_SOURCES = SHM_Transporter.cpp SHM_Transporter.unix.cpp S
libtransporter_la_LIBADD = @ndb_transporter_opt_objs@
libtransporter_la_DEPENDENCIES = @ndb_transporter_opt_objs@
-INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/include/debugger -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/include/transporter @NDB_SCI_INCLUDES@
+INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/mgmapi -I$(top_srcdir)/ndb/include/debugger -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/include/transporter @NDB_SCI_INCLUDES@
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/common/transporter/OSE_Transporter.cpp b/ndb/src/common/transporter/OSE_Transporter.cpp
index a52862a80e5..ad67791fc0c 100644
--- a/ndb/src/common/transporter/OSE_Transporter.cpp
+++ b/ndb/src/common/transporter/OSE_Transporter.cpp
@@ -32,6 +32,7 @@ OSE_Transporter::OSE_Transporter(int _prioASignalSize,
NodeId localNodeId,
const char * lHostName,
NodeId remoteNodeId,
+ NodeId serverNodeId,
const char * rHostName,
int byteorder,
bool compression,
@@ -40,6 +41,7 @@ OSE_Transporter::OSE_Transporter(int _prioASignalSize,
Uint32 reportFreq) :
Transporter(localNodeId,
remoteNodeId,
+ serverNodeId,
byteorder,
compression,
checksum,
diff --git a/ndb/src/common/transporter/OSE_Transporter.hpp b/ndb/src/common/transporter/OSE_Transporter.hpp
index 4fd06130477..898352366ba 100644
--- a/ndb/src/common/transporter/OSE_Transporter.hpp
+++ b/ndb/src/common/transporter/OSE_Transporter.hpp
@@ -48,6 +48,7 @@ public:
NodeId localNodeId,
const char * lHostName,
NodeId remoteNodeId,
+ NodeId serverNodeId,
const char * rHostName,
int byteorder,
bool compression,
diff --git a/ndb/src/common/transporter/Packer.cpp b/ndb/src/common/transporter/Packer.cpp
index 9eba335330d..bcfac8417bb 100644
--- a/ndb/src/common/transporter/Packer.cpp
+++ b/ndb/src/common/transporter/Packer.cpp
@@ -93,6 +93,7 @@ TransporterRegistry::unpack(Uint32 * readPtr,
signalHeader.theSendersSignalId = * signalData;
signalData ++;
}//if
+ signalHeader.theSignalId= ~0;
Uint32 * sectionPtr = signalData + signalHeader.theLength;
Uint32 * sectionData = sectionPtr + signalHeader.m_noOfSections;
diff --git a/ndb/src/common/transporter/SCI_Transporter.cpp b/ndb/src/common/transporter/SCI_Transporter.cpp
index 47722939098..1fe276249e5 100644
--- a/ndb/src/common/transporter/SCI_Transporter.cpp
+++ b/ndb/src/common/transporter/SCI_Transporter.cpp
@@ -34,19 +34,21 @@ SCI_Transporter::SCI_Transporter(TransporterRegistry &t_reg,
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
Uint32 packetSize,
Uint32 bufferSize,
Uint32 nAdapters,
Uint16 remoteSciNodeId0,
Uint16 remoteSciNodeId1,
NodeId _localNodeId,
- NodeId _remoteNodeId,
+ NodeId _remoteNodeId,
+ NodeId serverNodeId,
bool chksm,
bool signalId,
Uint32 reportFreq) :
Transporter(t_reg, tt_SCI_TRANSPORTER,
- lHostName, rHostName, r_port, _localNodeId,
- _remoteNodeId, 0, false, chksm, signalId)
+ lHostName, rHostName, r_port, isMgmConnection, _localNodeId,
+ _remoteNodeId, serverNodeId, 0, false, chksm, signalId)
{
DBUG_ENTER("SCI_Transporter::SCI_Transporter");
m_PacketSize = (packetSize + 3)/4 ;
diff --git a/ndb/src/common/transporter/SCI_Transporter.hpp b/ndb/src/common/transporter/SCI_Transporter.hpp
index e62c142e1b9..cb42e437118 100644
--- a/ndb/src/common/transporter/SCI_Transporter.hpp
+++ b/ndb/src/common/transporter/SCI_Transporter.hpp
@@ -140,13 +140,15 @@ private:
const char *local_host,
const char *remote_host,
int port,
+ bool isMgmConnection,
Uint32 packetSize,
Uint32 bufferSize,
Uint32 nAdapters,
Uint16 remoteSciNodeId0,
Uint16 remoteSciNodeId1,
NodeId localNodeID,
- NodeId remoteNodeID,
+ NodeId remoteNodeID,
+ NodeId serverNodeId,
bool checksum,
bool signalId,
Uint32 reportFreq = 4096);
diff --git a/ndb/src/common/transporter/SHM_Transporter.cpp b/ndb/src/common/transporter/SHM_Transporter.cpp
index 4d7f46d7723..93d718b8713 100644
--- a/ndb/src/common/transporter/SHM_Transporter.cpp
+++ b/ndb/src/common/transporter/SHM_Transporter.cpp
@@ -32,18 +32,24 @@ SHM_Transporter::SHM_Transporter(TransporterRegistry &t_reg,
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
bool checksum,
bool signalId,
key_t _shmKey,
Uint32 _shmSize) :
Transporter(t_reg, tt_SHM_TRANSPORTER,
- lHostName, rHostName, r_port, lNodeId, rNodeId,
+ lHostName, rHostName, r_port, isMgmConnection,
+ lNodeId, rNodeId, serverNodeId,
0, false, checksum, signalId),
shmKey(_shmKey),
shmSize(_shmSize)
{
+#ifndef NDB_WIN32
+ shmId= 0;
+#endif
_shmSegCreated = false;
_attached = false;
@@ -199,7 +205,8 @@ SHM_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd)
// Create
if(!_shmSegCreated){
if (!ndb_shm_create()) {
- report_error(TE_SHM_UNABLE_TO_CREATE_SEGMENT);
+ make_error_info(buf, sizeof(buf));
+ report_error(TE_SHM_UNABLE_TO_CREATE_SEGMENT, buf);
NDB_CLOSE_SOCKET(sockfd);
DBUG_RETURN(false);
}
@@ -209,7 +216,8 @@ SHM_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd)
// Attach
if(!_attached){
if (!ndb_shm_attach()) {
- report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT);
+ make_error_info(buf, sizeof(buf));
+ report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT, buf);
NDB_CLOSE_SOCKET(sockfd);
DBUG_RETURN(false);
}
@@ -221,7 +229,8 @@ SHM_Transporter::connect_server_impl(NDB_SOCKET_TYPE sockfd)
m_transporter_registry.m_shm_own_pid);
// Wait for ok from client
- if (s_input.gets(buf, 256) == 0)
+ DBUG_PRINT("info", ("Wait for ok from client"));
+ if (s_input.gets(buf, sizeof(buf)) == 0)
{
NDB_CLOSE_SOCKET(sockfd);
DBUG_RETURN(false);
@@ -259,10 +268,8 @@ SHM_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd)
SocketOutputStream s_output(sockfd);
char buf[256];
-#if 1
-#endif
-
// Wait for server to create and attach
+ DBUG_PRINT("info", ("Wait for server to create and attach"));
if (s_input.gets(buf, 256) == 0) {
NDB_CLOSE_SOCKET(sockfd);
DBUG_PRINT("error", ("Server id %d did not attach",
@@ -290,7 +297,8 @@ SHM_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd)
// Attach
if(!_attached){
if (!ndb_shm_attach()) {
- report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT);
+ make_error_info(buf, sizeof(buf));
+ report_error(TE_SHM_UNABLE_TO_ATTACH_SEGMENT, buf);
NDB_CLOSE_SOCKET(sockfd);
DBUG_PRINT("error", ("Failed attach of shm seg to node %d",
remoteNodeId));
@@ -307,6 +315,7 @@ SHM_Transporter::connect_client_impl(NDB_SOCKET_TYPE sockfd)
if (r) {
// Wait for ok from server
+ DBUG_PRINT("info", ("Wait for ok from server"));
if (s_input.gets(buf, 256) == 0) {
NDB_CLOSE_SOCKET(sockfd);
DBUG_PRINT("error", ("No ok from server node %d",
@@ -327,8 +336,6 @@ bool
SHM_Transporter::connect_common(NDB_SOCKET_TYPE sockfd)
{
if (!checkConnected()) {
- DBUG_PRINT("error", ("Already connected to node %d",
- remoteNodeId));
return false;
}
diff --git a/ndb/src/common/transporter/SHM_Transporter.hpp b/ndb/src/common/transporter/SHM_Transporter.hpp
index 7079e12a924..b25f9e538db 100644
--- a/ndb/src/common/transporter/SHM_Transporter.hpp
+++ b/ndb/src/common/transporter/SHM_Transporter.hpp
@@ -36,8 +36,10 @@ public:
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
bool checksum,
bool signalId,
key_t shmKey,
@@ -168,6 +170,8 @@ private:
bool hasDataToRead() const {
return reader->empty() == false;
}
+
+ void make_error_info(char info[], int sz);
};
#endif
diff --git a/ndb/src/common/transporter/SHM_Transporter.unix.cpp b/ndb/src/common/transporter/SHM_Transporter.unix.cpp
index 28882324fc0..7277f9e13ef 100644
--- a/ndb/src/common/transporter/SHM_Transporter.unix.cpp
+++ b/ndb/src/common/transporter/SHM_Transporter.unix.cpp
@@ -26,6 +26,12 @@
#include <sys/ipc.h>
#include <sys/shm.h>
+void SHM_Transporter::make_error_info(char info[], int sz)
+{
+ snprintf(info,sz,"Shm key=%d sz=%d id=%d",
+ shmKey, shmSize, shmId);
+}
+
bool
SHM_Transporter::ndb_shm_create()
{
@@ -64,12 +70,30 @@ SHM_Transporter::checkConnected(){
struct shmid_ds info;
const int res = shmctl(shmId, IPC_STAT, &info);
if(res == -1){
- report_error(TE_SHM_IPC_STAT);
+ char buf[128];
+ int r= snprintf(buf, sizeof(buf),
+ "shmctl(%d, IPC_STAT) errno: %d(%s). ", shmId,
+ errno, strerror(errno));
+ make_error_info(buf+r, sizeof(buf)-r);
+ DBUG_PRINT("error",(buf));
+ switch (errno)
+ {
+ case EACCES:
+ report_error(TE_SHM_IPC_PERMANENT, buf);
+ break;
+ default:
+ report_error(TE_SHM_IPC_STAT, buf);
+ break;
+ }
return false;
}
if(info.shm_nattch != 2){
+ char buf[128];
+ make_error_info(buf, sizeof(buf));
report_error(TE_SHM_DISCONNECT);
+ DBUG_PRINT("error", ("Already connected to node %d",
+ remoteNodeId));
return false;
}
return true;
@@ -91,6 +115,8 @@ SHM_Transporter::disconnectImpl(){
if(isServer && _shmSegCreated){
const int res = shmctl(shmId, IPC_RMID, 0);
if(res == -1){
+ char buf[64];
+ make_error_info(buf, sizeof(buf));
report_error(TE_SHM_UNABLE_TO_REMOVE_SEGMENT);
return;
}
diff --git a/ndb/src/common/transporter/SHM_Transporter.win32.cpp b/ndb/src/common/transporter/SHM_Transporter.win32.cpp
index c289a85da0e..86029b17885 100644
--- a/ndb/src/common/transporter/SHM_Transporter.win32.cpp
+++ b/ndb/src/common/transporter/SHM_Transporter.win32.cpp
@@ -26,6 +26,12 @@
#include <windows.h>
+void SHM_Transporter::make_error_info(char info[], int sz)
+{
+ snprintf(info,sz,"Shm key=%d sz=%d",
+ shmKey, shmSize);
+}
+
bool
SHM_Transporter::connectServer(Uint32 timeOutMillis){
if(!_shmSegCreated)
diff --git a/ndb/src/common/transporter/TCP_Transporter.cpp b/ndb/src/common/transporter/TCP_Transporter.cpp
index 5003d90a4b4..5db12d3985c 100644
--- a/ndb/src/common/transporter/TCP_Transporter.cpp
+++ b/ndb/src/common/transporter/TCP_Transporter.cpp
@@ -68,12 +68,15 @@ TCP_Transporter::TCP_Transporter(TransporterRegistry &t_reg,
const char *lHostName,
const char *rHostName,
int r_port,
+ bool isMgmConnection,
NodeId lNodeId,
NodeId rNodeId,
+ NodeId serverNodeId,
bool chksm, bool signalId,
Uint32 _reportFreq) :
Transporter(t_reg, tt_TCP_TRANSPORTER,
- lHostName, rHostName, r_port, lNodeId, rNodeId,
+ lHostName, rHostName, r_port, isMgmConnection,
+ lNodeId, rNodeId, serverNodeId,
0, false, chksm, signalId),
m_sendBuffer(sendBufSize)
{
diff --git a/ndb/src/common/transporter/TCP_Transporter.hpp b/ndb/src/common/transporter/TCP_Transporter.hpp
index 151ec261506..df4149531b4 100644
--- a/ndb/src/common/transporter/TCP_Transporter.hpp
+++ b/ndb/src/common/transporter/TCP_Transporter.hpp
@@ -49,9 +49,11 @@ private:
int sendBufferSize, int maxReceiveSize,
const char *lHostName,
const char *rHostName,
- int r_port,
+ int r_port,
+ bool isMgmConnection,
NodeId lHostId,
NodeId rHostId,
+ NodeId serverNodeId,
bool checksum, bool signalId,
Uint32 reportFreq = 4096);
diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp
index 902dfea9c8e..820aa4cfc18 100644
--- a/ndb/src/common/transporter/Transporter.cpp
+++ b/ndb/src/common/transporter/Transporter.cpp
@@ -31,13 +31,15 @@ Transporter::Transporter(TransporterRegistry &t_reg,
TransporterType _type,
const char *lHostName,
const char *rHostName,
- int r_port,
+ int s_port,
+ bool _isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
int _byteorder,
bool _compression, bool _checksum, bool _signalId)
- : m_r_port(r_port), remoteNodeId(rNodeId), localNodeId(lNodeId),
- isServer(lNodeId < rNodeId),
+ : m_s_port(s_port), remoteNodeId(rNodeId), localNodeId(lNodeId),
+ isServer(lNodeId==serverNodeId), isMgmConnection(_isMgmConnection),
m_packer(_signalId, _checksum),
m_type(_type),
m_transporter_registry(t_reg)
@@ -61,10 +63,10 @@ Transporter::Transporter(TransporterRegistry &t_reg,
if (strlen(lHostName) > 0)
Ndb_getInAddr(&localHostAddress, lHostName);
- DBUG_PRINT("info",("rId=%d lId=%d isServer=%d rHost=%s lHost=%s r_port=%d",
+ DBUG_PRINT("info",("rId=%d lId=%d isServer=%d rHost=%s lHost=%s s_port=%d",
remoteNodeId, localNodeId, isServer,
remoteHostName, localHostName,
- r_port));
+ s_port));
byteOrder = _byteorder;
compressionUsed = _compression;
@@ -75,10 +77,13 @@ Transporter::Transporter(TransporterRegistry &t_reg,
m_timeOutMillis = 1000;
m_connect_address.s_addr= 0;
+ if(s_port<0)
+ s_port= -s_port; // was dynamic
+
if (isServer)
m_socket_client= 0;
else
- m_socket_client= new SocketClient(remoteHostName, r_port,
+ m_socket_client= new SocketClient(remoteHostName, s_port,
new SocketAuthSimple("ndbd",
"ndbd passwd"));
DBUG_VOID_RETURN;
@@ -117,22 +122,42 @@ Transporter::connect_server(NDB_SOCKET_TYPE sockfd) {
bool
Transporter::connect_client() {
+ NDB_SOCKET_TYPE sockfd;
+
if(m_connected)
return true;
- NDB_SOCKET_TYPE sockfd = m_socket_client->connect();
-
+
+ if(isMgmConnection)
+ sockfd= m_transporter_registry.connect_ndb_mgmd(m_socket_client);
+ else
+ sockfd= m_socket_client->connect();
+
+ return connect_client(sockfd);
+}
+
+bool
+Transporter::connect_client(NDB_SOCKET_TYPE sockfd) {
+
+ if(m_connected)
+ return true;
+
if (sockfd == NDB_INVALID_SOCKET)
return false;
DBUG_ENTER("Transporter::connect_client");
+ DBUG_PRINT("info",("port %d isMgmConnection=%d",m_s_port,isMgmConnection));
+
+ SocketOutputStream s_output(sockfd);
+ SocketInputStream s_input(sockfd);
+
// send info about own id
// send info about own transporter type
- SocketOutputStream s_output(sockfd);
+
s_output.println("%d %d", localNodeId, m_type);
// get remote id
int nodeId, remote_transporter_type= -1;
- SocketInputStream s_input(sockfd);
+
char buf[256];
if (s_input.gets(buf, 256) == 0) {
NDB_CLOSE_SOCKET(sockfd);
diff --git a/ndb/src/common/transporter/Transporter.hpp b/ndb/src/common/transporter/Transporter.hpp
index 5f3f8063723..9e8bbd687ee 100644
--- a/ndb/src/common/transporter/Transporter.hpp
+++ b/ndb/src/common/transporter/Transporter.hpp
@@ -44,6 +44,7 @@ public:
* Use isConnected() to check status
*/
bool connect_client();
+ bool connect_client(NDB_SOCKET_TYPE sockfd);
bool connect_server(NDB_SOCKET_TYPE socket);
/**
@@ -69,6 +70,22 @@ public:
*/
NodeId getLocalNodeId() const;
+ /**
+ * Get port we're connecting to (signed)
+ */
+ int get_s_port() { return m_s_port; };
+
+ /**
+ * Set port to connect to (signed)
+ */
+ void set_s_port(int port) {
+ m_s_port = port;
+ if(port<0)
+ port= -port;
+ if(m_socket_client)
+ m_socket_client->set_port(port);
+ };
+
virtual Uint32 get_free_buffer() const = 0;
protected:
@@ -76,9 +93,11 @@ protected:
TransporterType,
const char *lHostName,
const char *rHostName,
- int r_port,
+ int s_port,
+ bool isMgmConnection,
NodeId lNodeId,
- NodeId rNodeId,
+ NodeId rNodeId,
+ NodeId serverNodeId,
int byteorder,
bool compression,
bool checksum,
@@ -104,7 +123,7 @@ protected:
struct in_addr remoteHostAddress;
struct in_addr localHostAddress;
- const unsigned int m_r_port;
+ int m_s_port;
const NodeId remoteNodeId;
const NodeId localNodeId;
@@ -121,6 +140,12 @@ protected:
private:
+ /**
+ * means that we transform an MGM connection into
+ * a transporter connection
+ */
+ bool isMgmConnection;
+
SocketClient *m_socket_client;
struct in_addr m_connect_address;
@@ -136,7 +161,8 @@ protected:
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);};
+ void report_error(enum TransporterError err, const char *info = 0)
+ { reportError(get_callback_obj(), remoteNodeId, err, info); };
};
inline
diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp
index 3f190d16264..cd78bc52027 100644
--- a/ndb/src/common/transporter/TransporterRegistry.cpp
+++ b/ndb/src/common/transporter/TransporterRegistry.cpp
@@ -48,6 +48,10 @@ extern int g_ndb_shm_signum;
#include <InputStream.hpp>
#include <OutputStream.hpp>
+#include <mgmapi/mgmapi.h>
+#include <mgmapi_internal.h>
+#include <mgmapi/mgmapi_debug.h>
+
#include <EventLogger.hpp>
extern EventLogger g_eventLogger;
@@ -83,6 +87,7 @@ TransporterRegistry::TransporterRegistry(void * callback,
nodeIdSpecified = false;
maxTransporters = _maxTransporters;
sendCounter = 1;
+ m_mgm_handle= 0;
callbackObj=callback;
@@ -119,6 +124,27 @@ TransporterRegistry::TransporterRegistry(void * callback,
DBUG_VOID_RETURN;
}
+void TransporterRegistry::set_mgm_handle(NdbMgmHandle h)
+{
+ DBUG_ENTER("TransporterRegistry::set_mgm_handle");
+ if (m_mgm_handle)
+ ndb_mgm_destroy_handle(&m_mgm_handle);
+ m_mgm_handle= h;
+#ifndef DBUG_OFF
+ if (h)
+ {
+ char buf[256];
+ DBUG_PRINT("info",("handle set with connectstring: %s",
+ ndb_mgm_get_connectstring(h,buf, sizeof(buf))));
+ }
+ else
+ {
+ DBUG_PRINT("info",("handle set to NULL"));
+ }
+#endif
+ DBUG_VOID_RETURN;
+}
+
TransporterRegistry::~TransporterRegistry()
{
DBUG_ENTER("TransporterRegistry::~TransporterRegistry");
@@ -141,6 +167,8 @@ TransporterRegistry::~TransporterRegistry()
theOSEReceiver = 0;
}
#endif
+ if (m_mgm_handle)
+ ndb_mgm_destroy_handle(&m_mgm_handle);
DBUG_VOID_RETURN;
}
@@ -258,7 +286,7 @@ TransporterRegistry::connect_server(NDB_SOCKET_TYPE sockfd)
}
bool
-TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
+TransporterRegistry::createTCPTransporter(TransporterConfiguration *config) {
#ifdef NDB_TCP_TRANSPORTER
if(!nodeIdSpecified){
@@ -272,13 +300,15 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
return false;
TCP_Transporter * t = new TCP_Transporter(*this,
- config->sendBufferSize,
- config->maxReceiveSize,
+ config->tcp.sendBufferSize,
+ config->tcp.maxReceiveSize,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
+ config->isMgmConnection,
localNodeId,
config->remoteNodeId,
+ config->serverNodeId,
config->checksum,
config->signalId);
if (t == NULL)
@@ -307,7 +337,7 @@ TransporterRegistry::createTransporter(TCP_TransporterConfiguration *config) {
}
bool
-TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
+TransporterRegistry::createOSETransporter(TransporterConfiguration *conf) {
#ifdef NDB_OSE_TRANSPORTER
if(!nodeIdSpecified){
@@ -326,11 +356,12 @@ TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
localNodeId);
}
- OSE_Transporter * t = new OSE_Transporter(conf->prioASignalSize,
- conf->prioBSignalSize,
+ OSE_Transporter * t = new OSE_Transporter(conf->ose.prioASignalSize,
+ conf->ose.prioBSignalSize,
localNodeId,
conf->localHostName,
conf->remoteNodeId,
+ conf->serverNodeId,
conf->remoteHostName,
conf->checksum,
conf->signalId);
@@ -356,7 +387,7 @@ TransporterRegistry::createTransporter(OSE_TransporterConfiguration *conf) {
}
bool
-TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
+TransporterRegistry::createSCITransporter(TransporterConfiguration *config) {
#ifdef NDB_SCI_TRANSPORTER
if(!SCI_Transporter::initSCI())
@@ -375,14 +406,16 @@ TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
SCI_Transporter * t = new SCI_Transporter(*this,
config->localHostName,
config->remoteHostName,
- config->port,
- config->sendLimit,
- config->bufferSize,
- config->nLocalAdapters,
- config->remoteSciNodeId0,
- config->remoteSciNodeId1,
+ config->s_port,
+ config->isMgmConnection,
+ config->sci.sendLimit,
+ config->sci.bufferSize,
+ config->sci.nLocalAdapters,
+ config->sci.remoteSciNodeId0,
+ config->sci.remoteSciNodeId1,
localNodeId,
config->remoteNodeId,
+ config->serverNodeId,
config->checksum,
config->signalId);
@@ -407,7 +440,7 @@ TransporterRegistry::createTransporter(SCI_TransporterConfiguration *config) {
}
bool
-TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
+TransporterRegistry::createSHMTransporter(TransporterConfiguration *config) {
DBUG_ENTER("TransporterRegistry::createTransporter SHM");
#ifdef NDB_SHM_TRANSPORTER
if(!nodeIdSpecified){
@@ -418,7 +451,7 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
return false;
if (!g_ndb_shm_signum) {
- g_ndb_shm_signum= config->signum;
+ g_ndb_shm_signum= config->shm.signum;
DBUG_PRINT("info",("Block signum %d",g_ndb_shm_signum));
/**
* Make sure to block g_ndb_shm_signum
@@ -430,7 +463,7 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
pthread_sigmask(SIG_BLOCK, &mask, 0);
}
- if(config->signum != g_ndb_shm_signum)
+ if(config->shm.signum != g_ndb_shm_signum)
return false;
if(theTransporters[config->remoteNodeId] != NULL)
@@ -439,13 +472,15 @@ TransporterRegistry::createTransporter(SHM_TransporterConfiguration *config) {
SHM_Transporter * t = new SHM_Transporter(*this,
config->localHostName,
config->remoteHostName,
- config->port,
+ config->s_port,
+ config->isMgmConnection,
localNodeId,
config->remoteNodeId,
+ config->serverNodeId,
config->checksum,
config->signalId,
- config->shmKey,
- config->shmSize
+ config->shm.shmKey,
+ config->shm.shmSize
);
if (t == NULL)
return false;
@@ -883,6 +918,7 @@ TransporterRegistry::performReceive()
NodeId remoteNodeId;
Uint32 * readPtr;
Uint32 sz = theOSEReceiver->getReceiveData(&remoteNodeId, &readPtr);
+ transporter_recv_from(callbackObj, remoteNodeId);
Uint32 szUsed = unpack(readPtr,
sz,
remoteNodeId,
@@ -918,6 +954,7 @@ TransporterRegistry::performReceive()
{
Uint32 * ptr;
Uint32 sz = t->getReceiveData(&ptr);
+ transporter_recv_from(callbackObj, nodeId);
Uint32 szUsed = unpack(ptr, sz, nodeId, ioStates[nodeId]);
t->updateReceiveDataPtr(szUsed);
}
@@ -941,6 +978,7 @@ TransporterRegistry::performReceive()
{
Uint32 * readPtr, * eodPtr;
t->getReceivePtr(&readPtr, &eodPtr);
+ transporter_recv_from(callbackObj, nodeId);
Uint32 *newPtr = unpack(readPtr, eodPtr, nodeId, ioStates[nodeId]);
t->updateReceivePtr(newPtr);
}
@@ -958,6 +996,7 @@ TransporterRegistry::performReceive()
{
Uint32 * readPtr, * eodPtr;
t->getReceivePtr(&readPtr, &eodPtr);
+ transporter_recv_from(callbackObj, nodeId);
Uint32 *newPtr = unpack(readPtr, eodPtr, nodeId, ioStates[nodeId]);
t->updateReceivePtr(newPtr);
}
@@ -1149,7 +1188,10 @@ TransporterRegistry::do_connect(NodeId node_id)
case DISCONNECTING:
break;
}
+ DBUG_ENTER("TransporterRegistry::do_connect");
+ DBUG_PRINT("info",("performStates[%d]=CONNECTING",node_id));
curr_state= CONNECTING;
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::do_disconnect(NodeId node_id)
@@ -1165,21 +1207,30 @@ TransporterRegistry::do_disconnect(NodeId node_id)
case DISCONNECTING:
return;
}
+ DBUG_ENTER("TransporterRegistry::do_disconnect");
+ DBUG_PRINT("info",("performStates[%d]=DISCONNECTING",node_id));
curr_state= DISCONNECTING;
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::report_connect(NodeId node_id)
{
+ DBUG_ENTER("TransporterRegistry::report_connect");
+ DBUG_PRINT("info",("performStates[%d]=CONNECTED",node_id));
performStates[node_id] = CONNECTED;
reportConnect(callbackObj, node_id);
+ DBUG_VOID_RETURN;
}
void
TransporterRegistry::report_disconnect(NodeId node_id, int errnum)
{
+ DBUG_ENTER("TransporterRegistry::report_disconnect");
+ DBUG_PRINT("info",("performStates[%d]=DISCONNECTED",node_id));
performStates[node_id] = DISCONNECTED;
reportDisconnect(callbackObj, node_id, errnum);
+ DBUG_VOID_RETURN;
}
void
@@ -1224,8 +1275,67 @@ TransporterRegistry::start_clients_thread()
const NodeId nodeId = t->getRemoteNodeId();
switch(performStates[nodeId]){
case CONNECTING:
- if(!t->isConnected() && !t->isServer)
- t->connect_client();
+ if(!t->isConnected() && !t->isServer) {
+ bool connected= false;
+ /**
+ * First, we try to connect (if we have a port number).
+ */
+ if (t->get_s_port())
+ connected= t->connect_client();
+
+ /**
+ * If dynamic, get the port for connecting from the management server
+ */
+ if( !connected && t->get_s_port() <= 0) { // Port is dynamic
+ int server_port= 0;
+ struct ndb_mgm_reply mgm_reply;
+
+ if(!ndb_mgm_is_connected(m_mgm_handle))
+ ndb_mgm_connect(m_mgm_handle, 0, 0, 0);
+
+ if(ndb_mgm_is_connected(m_mgm_handle))
+ {
+ int res=
+ ndb_mgm_get_connection_int_parameter(m_mgm_handle,
+ t->getRemoteNodeId(),
+ t->getLocalNodeId(),
+ CFG_CONNECTION_SERVER_PORT,
+ &server_port,
+ &mgm_reply);
+ DBUG_PRINT("info",("Got dynamic port %d for %d -> %d (ret: %d)",
+ server_port,t->getRemoteNodeId(),
+ t->getLocalNodeId(),res));
+ if( res >= 0 )
+ {
+ /**
+ * Server_port == 0 just means that that a mgmt server
+ * has not received a new port yet. Keep the old.
+ */
+ if (server_port)
+ t->set_s_port(server_port);
+ }
+ else if(ndb_mgm_is_connected(m_mgm_handle))
+ {
+ ndbout_c("Failed to get dynamic port to connect to: %d", res);
+ ndb_mgm_disconnect(m_mgm_handle);
+ }
+ else
+ {
+ ndbout_c("Management server closed connection early. "
+ "It is probably being shut down (or has problems). "
+ "We will retry the connection.");
+ }
+ }
+ /** else
+ * We will not be able to get a new port unless
+ * the m_mgm_handle is connected. Note that not
+ * being connected is an ok state, just continue
+ * until it is able to connect. Continue using the
+ * old port until we can connect again and get a
+ * new port.
+ */
+ }
+ }
break;
case DISCONNECTING:
if(t->isConnected())
@@ -1261,24 +1371,26 @@ 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_WaitFor(m_start_clients_thread, &status);
NdbThread_Destroy(&m_start_clients_thread);
}
return true;
}
void
-TransporterRegistry::add_transporter_interface(const char *interf, unsigned short port)
+TransporterRegistry::add_transporter_interface(NodeId remoteNodeId,
+ const char *interf,
+ int s_port)
{
DBUG_ENTER("TransporterRegistry::add_transporter_interface");
- DBUG_PRINT("enter",("interface=%s, port= %d", interf, port));
+ DBUG_PRINT("enter",("interface=%s, s_port= %d", interf, s_port));
if (interf && strlen(interf) == 0)
interf= 0;
for (unsigned i= 0; i < m_transporter_interface.size(); i++)
{
Transporter_interface &tmp= m_transporter_interface[i];
- if (port != tmp.m_service_port)
+ if (s_port != tmp.m_s_service_port || tmp.m_s_service_port==0)
continue;
if (interf != 0 && tmp.m_interface != 0 &&
strcmp(interf, tmp.m_interface) == 0)
@@ -1291,7 +1403,8 @@ TransporterRegistry::add_transporter_interface(const char *interf, unsigned shor
}
}
Transporter_interface t;
- t.m_service_port= port;
+ t.m_remote_nodeId= remoteNodeId;
+ t.m_s_service_port= s_port;
t.m_interface= interf;
m_transporter_interface.push_back(t);
DBUG_PRINT("exit",("interface and port added"));
@@ -1301,34 +1414,50 @@ TransporterRegistry::add_transporter_interface(const char *interf, unsigned shor
bool
TransporterRegistry::start_service(SocketServer& socket_server)
{
+ struct ndb_mgm_reply mgm_reply;
+
+ DBUG_ENTER("TransporterRegistry::start_service");
if (m_transporter_interface.size() > 0 && !nodeIdSpecified)
{
ndbout_c("TransporterRegistry::startReceiving: localNodeId not specified");
- return false;
+ DBUG_RETURN(false);
}
for (unsigned i= 0; i < m_transporter_interface.size(); i++)
{
Transporter_interface &t= m_transporter_interface[i];
- if (t.m_service_port == 0)
- {
- continue;
- }
+
+ unsigned short port= (unsigned short)t.m_s_service_port;
+ if(t.m_s_service_port<0)
+ port= -t.m_s_service_port; // is a dynamic port
TransporterService *transporter_service =
new TransporterService(new SocketAuthSimple("ndbd", "ndbd passwd"));
if(!socket_server.setup(transporter_service,
- t.m_service_port, t.m_interface))
+ &port, t.m_interface))
{
- ndbout_c("Unable to setup transporter service port: %s:%d!\n"
- "Please check if the port is already used,\n"
- "(perhaps the node is already running)",
- t.m_interface ? t.m_interface : "*", t.m_service_port);
- delete transporter_service;
- return false;
+ DBUG_PRINT("info", ("Trying new port"));
+ port= 0;
+ if(t.m_s_service_port>0
+ || !socket_server.setup(transporter_service,
+ &port, t.m_interface))
+ {
+ /*
+ * If it wasn't a dynamically allocated port, or
+ * our attempts at getting a new dynamic port failed
+ */
+ ndbout_c("Unable to setup transporter service port: %s:%d!\n"
+ "Please check if the port is already used,\n"
+ "(perhaps the node is already running)",
+ t.m_interface ? t.m_interface : "*", t.m_s_service_port);
+ delete transporter_service;
+ DBUG_RETURN(false);
+ }
}
+ t.m_s_service_port= (t.m_s_service_port<=0)?-port:port; // -`ve if dynamic
+ DBUG_PRINT("info", ("t.m_s_service_port = %d",t.m_s_service_port));
transporter_service->setTransporterRegistry(this);
}
- return true;
+ DBUG_RETURN(true);
}
#ifdef NDB_SHM_TRANSPORTER
@@ -1379,13 +1508,8 @@ TransporterRegistry::startReceiving()
{
DBUG_PRINT("error",("Install failed"));
g_eventLogger.error("Failed to install signal handler for"
- " SHM transporter errno: %d (%s)", errno,
-#ifdef HAVE_STRERROR
- strerror(errno)
-#else
- ""
-#endif
- );
+ " SHM transporter, signum %d, errno: %d (%s)",
+ g_ndb_shm_signum, errno, strerror(errno));
}
}
#endif // NDB_SHM_TRANSPORTER
@@ -1443,4 +1567,107 @@ NdbOut & operator <<(NdbOut & out, SignalHeader & sh){
return out;
}
+Transporter*
+TransporterRegistry::get_transporter(NodeId nodeId) {
+ return theTransporters[nodeId];
+}
+
+bool TransporterRegistry::connect_client(NdbMgmHandle *h)
+{
+ DBUG_ENTER("TransporterRegistry::connect_client(NdbMgmHandle)");
+
+ Uint32 mgm_nodeid= ndb_mgm_get_mgmd_nodeid(*h);
+
+ if(!mgm_nodeid)
+ {
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ return false;
+ }
+ Transporter * t = theTransporters[mgm_nodeid];
+ if (!t)
+ {
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ return false;
+ }
+ DBUG_RETURN(t->connect_client(connect_ndb_mgmd(h)));
+}
+
+/**
+ * Given a connected NdbMgmHandle, turns it into a transporter
+ * and returns the socket.
+ */
+NDB_SOCKET_TYPE TransporterRegistry::connect_ndb_mgmd(NdbMgmHandle *h)
+{
+ struct ndb_mgm_reply mgm_reply;
+
+ if ( h==NULL || *h == NULL )
+ {
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ return NDB_INVALID_SOCKET;
+ }
+
+ for(unsigned int i=0;i < m_transporter_interface.size();i++)
+ if (m_transporter_interface[i].m_s_service_port < 0
+ && ndb_mgm_set_connection_int_parameter(*h,
+ get_localNodeId(),
+ m_transporter_interface[i].m_remote_nodeId,
+ CFG_CONNECTION_SERVER_PORT,
+ m_transporter_interface[i].m_s_service_port,
+ &mgm_reply) < 0)
+ {
+ ndbout_c("Error: %s: %d",
+ ndb_mgm_get_latest_error_desc(*h),
+ ndb_mgm_get_latest_error(*h));
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ ndb_mgm_destroy_handle(h);
+ return NDB_INVALID_SOCKET;
+ }
+
+ /**
+ * convert_to_transporter also disposes of the handle (i.e. we don't leak
+ * memory here.
+ */
+ NDB_SOCKET_TYPE sockfd= ndb_mgm_convert_to_transporter(h);
+ if ( sockfd == NDB_INVALID_SOCKET)
+ {
+ ndbout_c("Error: %s: %d",
+ ndb_mgm_get_latest_error_desc(*h),
+ ndb_mgm_get_latest_error(*h));
+ ndbout_c("%s: %d", __FILE__, __LINE__);
+ ndb_mgm_destroy_handle(h);
+ }
+ return sockfd;
+}
+
+/**
+ * Given a SocketClient, creates a NdbMgmHandle, turns it into a transporter
+ * and returns the socket.
+ */
+NDB_SOCKET_TYPE TransporterRegistry::connect_ndb_mgmd(SocketClient *sc)
+{
+ NdbMgmHandle h= ndb_mgm_create_handle();
+
+ if ( h == NULL )
+ {
+ return NDB_INVALID_SOCKET;
+ }
+
+ /**
+ * Set connectstring
+ */
+ {
+ BaseString cs;
+ cs.assfmt("%s:%u",sc->get_server_name(),sc->get_port());
+ ndb_mgm_set_connectstring(h, cs.c_str());
+ }
+
+ if(ndb_mgm_connect(h, 0, 0, 0)<0)
+ {
+ ndb_mgm_destroy_handle(&h);
+ return NDB_INVALID_SOCKET;
+ }
+
+ return connect_ndb_mgmd(&h);
+}
+
template class Vector<TransporterRegistry::Transporter_interface>;
diff --git a/ndb/src/common/util/Base64.cpp b/ndb/src/common/util/Base64.cpp
deleted file mode 100644
index f7a490d427d..00000000000
--- a/ndb/src/common/util/Base64.cpp
+++ /dev/null
@@ -1,207 +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 <ndb_global.h>
-#include <Base64.hpp>
-
-static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/";
-
-int
-base64_encode(const UtilBuffer &src, BaseString &dst) {
- const unsigned char *s = (const unsigned char *)src.get_data();
- size_t i = 0;
- size_t len = 0;
- size_t src_len = src.length();
- while(i < src_len) {
- if(len == 76){
- len = 0;
- dst.append('\n');
- }
-
- unsigned c;
- c = s[i++];
- c <<= 8;
-
- if(i < src_len)
- c += s[i];
- c <<= 8;
- i++;
-
- if(i < src_len)
- c += s[i];
- i++;
-
- dst.append(base64_table[(c >> 18) & 0x3f]);
- dst.append(base64_table[(c >> 12) & 0x3f]);
-
- if(i > (src_len + 1))
- dst.append('=');
- else
- dst.append(base64_table[(c >> 6) & 0x3f]);
-
- if(i > src_len)
- dst.append('=');
- else
- dst.append(base64_table[(c >> 0) & 0x3f]);
-
- len += 4;
- }
- return 0;
-}
-
-static inline unsigned
-pos(unsigned char c) {
- return strchr(base64_table, c) - base64_table;
-}
-
-
-int
-base64_decode(const BaseString &src, UtilBuffer &dst) {
- return base64_decode(src.c_str(), src.length(), dst);
-}
-
-#define SKIP_SPACE(src, i, size){ \
- while(i < size && isspace(* src)){ \
- i++; \
- src++; \
- } \
- if(i == size){ \
- i = size + 1; \
- break; \
- } \
-}
-
-int
-base64_decode(const char * src, size_t size, UtilBuffer &dst) {
- size_t i = 0;
- while(i < size){
- unsigned c = 0;
- int mark = 0;
-
- SKIP_SPACE(src, i, size);
-
- c += pos(*src++);
- c <<= 6;
- i++;
-
- SKIP_SPACE(src, i, size);
-
- c += pos(*src++);
- c <<= 6;
- i++;
-
- SKIP_SPACE(src, i, size);
-
- if(* src != '=')
- c += pos(*src++);
- else {
- i = size;
- mark = 2;
- c <<= 6;
- goto end;
- }
- c <<= 6;
- i++;
-
- SKIP_SPACE(src, i, size);
-
- if(*src != '=')
- c += pos(*src++);
- else {
- i = size;
- mark = 1;
- goto end;
- }
- i++;
-
- end:
- char b[3];
- b[0] = (c >> 16) & 0xff;
- b[1] = (c >> 8) & 0xff;
- b[2] = (c >> 0) & 0xff;
-
- dst.append((void *)b, 3-mark);
- }
-
- if(i != size){
- abort();
- return -1;
- }
- return 0;
-}
-
-#ifdef __TEST__B64
-/**
- * USER_FLAGS="-D__TEST__B64" make Base64.o && g++ Base64.o BaseString.o
- */
-inline
-void
-require(bool b){
- if(!b)
- abort();
-}
-
-int
-main(void){
- for(int i = 0; i < 500; i++){
- const size_t len = rand() % 10000 + 1;
- UtilBuffer src;
- for(size_t j = 0; j<len; j++){
- char c = rand();
- src.append(&c, 1);
- }
- require(src.length() == len);
-
- BaseString str;
- require(base64_encode(src, str) == 0);
-
- if(str.length() == 3850){
- printf(">%s<\n", str.c_str());
- }
-
- UtilBuffer dst;
- require(base64_decode(str, dst) == 0);
- require(dst.length() == src.length());
-
- const char * c_src = (char*)src.get_data();
- const char * c_dst = (char*)dst.get_data();
- if(memcmp(src.get_data(), dst.get_data(), src.length()) != 0){
- printf("-- src --\n");
- for(int i2 = 0; i2<len; i2++){
- unsigned char c = c_src[i2];
- printf("%.2x ", (unsigned)c);
- if((i2 % 8) == 7)
- printf("\n");
- }
- printf("\n");
-
- printf("-- dst --\n");
- for(int i2 = 0; i2<len; i2++){
- unsigned char c = c_dst[i2];
- printf("%.2x ", (unsigned)c);
- if((i2 % 8) == 7)
- printf("\n");
- }
- printf("\n");
- abort();
- }
- }
- return 0;
-}
-
-#endif
diff --git a/ndb/src/common/util/Bitmask.cpp b/ndb/src/common/util/Bitmask.cpp
new file mode 100644
index 00000000000..0aa39a37204
--- /dev/null
+++ b/ndb/src/common/util/Bitmask.cpp
@@ -0,0 +1,351 @@
+#include <Bitmask.hpp>
+#include <NdbOut.hpp>
+
+static
+void print(const Uint32 src[], Uint32 len, Uint32 pos = 0)
+{
+ printf("b'");
+ for(unsigned i = 0; i<len; i++)
+ {
+ if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos))
+ printf("1");
+ else
+ printf("0");
+ if((i & 31) == 31)
+ printf(" ");
+ }
+}
+
+#ifndef __TEST_BITMASK__
+
+void
+BitmaskImpl::getFieldImpl(const Uint32 src[],
+ unsigned shiftL, unsigned len, Uint32 dst[])
+{
+ assert(shiftL < 32);
+
+ unsigned shiftR = 32 - shiftL;
+ unsigned undefined = shiftL ? ~0 : 0;
+
+ * dst = shiftL ? * dst : 0;
+
+ while(len >= 32)
+ {
+ * dst++ |= (* src) << shiftL;
+ * dst = ((* src++) >> shiftR) & undefined;
+ len -= 32;
+ }
+
+ if(len < shiftR)
+ {
+ * dst |= ((* src) & ((1 << len) - 1)) << shiftL;
+ }
+ else
+ {
+ * dst++ |= ((* src) << shiftL);
+ * dst = ((* src) >> shiftR) & ((1 << (len - shiftR)) - 1) & undefined;
+ }
+}
+
+void
+BitmaskImpl::setFieldImpl(Uint32 dst[],
+ unsigned shiftL, unsigned len, const Uint32 src[])
+{
+ /**
+ *
+ * abcd ef00
+ * 00ab cdef
+ */
+ assert(shiftL < 32);
+ unsigned shiftR = 32 - shiftL;
+ unsigned undefined = shiftL ? ~0 : 0;
+ while(len >= 32)
+ {
+ * dst = (* src++) >> shiftL;
+ * dst++ |= ((* src) << shiftR) & undefined;
+ len -= 32;
+ }
+
+ Uint32 mask = ((1 << len) -1);
+ * dst = (* dst & ~mask);
+ if(len < shiftR)
+ {
+ * dst |= ((* src++) >> shiftL) & mask;
+ }
+ else
+ {
+ * dst |= ((* src++) >> shiftL);
+ * dst |= ((* src) & ((1 << (len - shiftR)) - 1)) << shiftR ;
+ }
+}
+#else
+
+#define DEBUG 0
+#include <Vector.hpp>
+static void do_test(int bitmask_size);
+
+int
+main(int argc, char** argv)
+{
+ int loops = argc > 1 ? atoi(argv[1]) : 1000;
+ int max_size = argc > 2 ? atoi(argv[2]) : 1000;
+
+
+ for(int i = 0; i<loops; i++)
+ do_test(1 + (rand() % max_size));
+}
+
+struct Alloc
+{
+ Uint32 pos;
+ Uint32 size;
+ Vector<Uint32> data;
+};
+
+static void require(bool b)
+{
+ if(!b) abort();
+}
+
+static
+bool cmp(const Uint32 b1[], const Uint32 b2[], Uint32 len)
+{
+ Uint32 sz32 = (len + 31) >> 5;
+ for(int i = 0; i<len; i++)
+ {
+ if(BitmaskImpl::get(sz32, b1, i) ^ BitmaskImpl::get(sz32, b2, i))
+ return false;
+ }
+ return true;
+}
+
+
+static int val_pos = 0;
+static int val[] = { 384, 241, 32,
+ 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0,
+ 241 };
+
+static int lrand()
+{
+#if 0
+ return val[val_pos++];
+#else
+ return rand();
+#endif
+}
+
+static
+void rand(Uint32 dst[], Uint32 len)
+{
+ for(int i = 0; i<len; i++)
+ BitmaskImpl::set((len + 31) >> 5, dst, i, (lrand() % 1000) > 500);
+}
+
+static
+void simple(int pos, int size)
+{
+ ndbout_c("simple pos: %d size: %d", pos, size);
+ Vector<Uint32> _mask;
+ Vector<Uint32> _src;
+ Vector<Uint32> _dst;
+ Uint32 sz32 = (size + pos + 32) >> 5;
+ const Uint32 sz = 4 * sz32;
+
+ Uint32 zero = 0;
+ _mask.fill(sz32+1, zero);
+ _src.fill(sz32+1, zero);
+ _dst.fill(sz32+1, zero);
+
+ Uint32 * src = _src.getBase();
+ Uint32 * dst = _dst.getBase();
+ Uint32 * mask = _mask.getBase();
+
+ memset(src, 0x0, sz);
+ memset(dst, 0x0, sz);
+ memset(mask, 0xFF, sz);
+ rand(src, size);
+ BitmaskImpl::setField(sz32, mask, pos, size, src);
+ BitmaskImpl::getField(sz32, mask, pos, size, dst);
+ printf("src: "); print(src, size+31); printf("\n");
+ printf("msk: "); print(mask, (sz32 << 5) + 31); printf("\n");
+ printf("dst: "); print(dst, size+31); printf("\n");
+ require(cmp(src, dst, size+31));
+};
+
+static
+void simple2(int size, int loops)
+{
+ ndbout_c("simple2 %d - ", size);
+ Vector<Uint32> _mask;
+ Vector<Uint32> _src;
+ Vector<Uint32> _dst;
+
+ Uint32 sz32 = (size + 32) >> 5;
+ Uint32 sz = sz32 << 2;
+
+ Uint32 zero = 0;
+ _mask.fill(sz32+1, zero);
+ _src.fill(sz32+1, zero);
+ _dst.fill(sz32+1, zero);
+
+ Uint32 * src = _src.getBase();
+ Uint32 * dst = _dst.getBase();
+ Uint32 * mask = _mask.getBase();
+
+ Vector<Uint32> save;
+ for(int i = 0; i<loops; i++)
+ {
+ memset(mask, 0xFF, sz);
+ memset(dst, 0xFF, sz);
+ int len;
+ int pos = 0;
+ while(pos+1 < size)
+ {
+ memset(src, 0xFF, sz);
+ while(!(len = rand() % (size - pos)));
+ BitmaskImpl::setField(sz32, mask, pos, len, src);
+ if(memcmp(dst, mask, sz))
+ {
+ ndbout_c("pos: %d len: %d", pos, len);
+ print(mask, size);
+ abort();
+ }
+ printf("[ %d %d ]", pos, len);
+ save.push_back(pos);
+ save.push_back(len);
+ pos += len;
+ }
+
+ for(int j = 0; j<save.size(); )
+ {
+ pos = save[j++];
+ len = save[j++];
+ memset(src, 0xFF, sz);
+ BitmaskImpl::getField(sz32, mask, pos, len, src);
+ if(memcmp(dst, src, sz))
+ {
+ ndbout_c("pos: %d len: %d", pos, len);
+ printf("src: "); print(src, size); printf("\n");
+ printf("dst: "); print(dst, size); printf("\n");
+ printf("msk: "); print(mask, size); printf("\n");
+ abort();
+ }
+ }
+ ndbout_c("");
+ }
+}
+
+static void
+do_test(int bitmask_size)
+{
+#if 1
+ simple(rand() % 33, (rand() % 63)+1);
+//#else
+ Vector<Alloc> alloc_list;
+ bitmask_size = (bitmask_size + 31) & ~31;
+ Uint32 sz32 = (bitmask_size >> 5);
+ Vector<Uint32> alloc_mask;
+ Vector<Uint32> test_mask;
+
+ ndbout_c("Testing bitmask of size %d", bitmask_size);
+ Uint32 zero = 0;
+ alloc_mask.fill(sz32, zero);
+ test_mask.fill(sz32, zero);
+
+ for(int i = 0; i<5000; i++)
+ {
+ Vector<Uint32> tmp;
+ tmp.fill(sz32, zero);
+
+ int pos = lrand() % (bitmask_size - 1);
+ int free = 0;
+ if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos))
+ {
+ // Bit was allocated
+ // 1) Look up allocation
+ // 2) Check data
+ // 3) free it
+ size_t j;
+ int min, max;
+ for(j = 0; j<alloc_list.size(); j++)
+ {
+ min = alloc_list[j].pos;
+ max = min + alloc_list[j].size;
+ if(pos >= min && pos < max)
+ {
+ break;
+ }
+ }
+ require(pos >= min && pos < max);
+ BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min,
+ tmp.getBase());
+ if(DEBUG)
+ {
+ printf("freeing [ %d %d ]", min, max);
+ printf("- mask: ");
+ print(tmp.getBase(), max - min);
+
+ printf(" save: ");
+ size_t k;
+ Alloc& a = alloc_list[j];
+ for(k = 0; k<a.data.size(); k++)
+ printf("%.8x ", a.data[k]);
+ printf("\n");
+ }
+ int bytes = (max - min + 7) >> 3;
+ if(!cmp(tmp.getBase(), alloc_list[j].data.getBase(), max - min))
+ {
+ abort();
+ }
+ while(min < max)
+ BitmaskImpl::clear(sz32, alloc_mask.getBase(), min++);
+ alloc_list.erase(j);
+ }
+ else
+ {
+ Vector<Uint32> tmp;
+ tmp.fill(sz32, zero);
+
+ // Bit was free
+ // 1) Check how much space is avaiable
+ // 2) Create new allocation of lrandom size
+ // 3) Fill data with lrandom data
+ // 4) Update alloc mask
+ while(pos+free < bitmask_size &&
+ !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free))
+ free++;
+
+ Uint32 sz =
+ (free <= 64 && ((lrand() % 100) > 80)) ? free : (lrand() % free);
+ sz = sz ? sz : 1;
+ sz = pos + sz == bitmask_size ? sz - 1 : sz;
+ Alloc a;
+ a.pos = pos;
+ a.size = sz;
+ a.data.fill(((sz+31)>> 5)-1, zero);
+ if(DEBUG)
+ printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz);
+ for(size_t j = 0; j<sz; j++)
+ {
+ BitmaskImpl::set(sz32, alloc_mask.getBase(), pos+j);
+ if((lrand() % 1000) > 500)
+ BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j);
+ }
+ if(DEBUG)
+ {
+ printf("- mask: ");
+ print(a.data.getBase(), sz);
+ printf("\n");
+ }
+ BitmaskImpl::setField(sz32, test_mask.getBase(), pos, sz,
+ a.data.getBase());
+ alloc_list.push_back(a);
+ }
+ }
+#endif
+}
+
+template class Vector<Alloc>;
+template class Vector<Uint32>;
+
+#endif
diff --git a/ndb/src/common/util/ConfigValues.cpp b/ndb/src/common/util/ConfigValues.cpp
index 5c4b17c73ca..ae4fbfd2f71 100644
--- a/ndb/src/common/util/ConfigValues.cpp
+++ b/ndb/src/common/util/ConfigValues.cpp
@@ -294,6 +294,12 @@ ConfigValuesFactory::ConfigValuesFactory(ConfigValues * cfg){
}
}
+ConfigValuesFactory::~ConfigValuesFactory()
+{
+ if(m_cfg)
+ free(m_cfg);
+}
+
ConfigValues *
ConfigValuesFactory::create(Uint32 keys, Uint32 data){
Uint32 sz = sizeof(ConfigValues);
@@ -528,7 +534,7 @@ ConfigValuesFactory::extractCurrentSection(const ConfigValues::ConstIterator & c
}
}
- ConfigValues * ret = fac->m_cfg;
+ ConfigValues * ret = fac->getConfigValues();
delete fac;
return ret;
}
diff --git a/ndb/src/common/util/File.cpp b/ndb/src/common/util/File.cpp
index e514ad8e122..52ad3a4a51e 100644
--- a/ndb/src/common/util/File.cpp
+++ b/ndb/src/common/util/File.cpp
@@ -67,7 +67,7 @@ File_class::File_class(const char* aFileName, const char* mode) :
m_file(NULL),
m_fileMode(mode)
{
- BaseString::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName);
+ BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
}
bool
@@ -83,7 +83,7 @@ File_class::open(const char* aFileName, const char* mode)
/**
* Only copy if it's not the same string
*/
- BaseString::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName);
+ BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
}
m_fileMode = mode;
bool rc = true;
diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am
index a62c8186174..75a1d970f7a 100644
--- a/ndb/src/common/util/Makefile.am
+++ b/ndb/src/common/util/Makefile.am
@@ -5,11 +5,28 @@ libgeneral_la_SOURCES = \
File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
SimpleProperties.cpp Parser.cpp InputStream.cpp \
SocketServer.cpp SocketClient.cpp SocketAuthenticator.cpp\
- OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
+ OutputStream.cpp NdbOut.cpp BaseString.cpp \
NdbSqlUtil.cpp new.cpp \
uucode.c random.c version.c \
strdup.c \
- ConfigValues.cpp ndb_init.c basestring_vsnprintf.c
+ ConfigValues.cpp ndb_init.c basestring_vsnprintf.c \
+ Bitmask.cpp
+
+EXTRA_PROGRAMS = testBitmask
+testBitmask_SOURCES = testBitmask.cpp
+testBitmask_LDFLAGS = @ndb_bin_am_ldflags@ \
+ $(top_builddir)/ndb/src/libndbclient.la \
+ $(top_builddir)/dbug/libdbug.a \
+ $(top_builddir)/mysys/libmysys.a \
+ $(top_builddir)/strings/libmystrings.a
+
+testBitmask.cpp : Bitmask.cpp
+ rm -f testBitmask.cpp
+ @LN_CP_F@ Bitmask.cpp testBitmask.cpp
+
+testBitmask.o: $(testBitmask_SOURCES)
+ $(CXXCOMPILE) -c $(INCLUDES) -D__TEST_BITMASK__ $<
+
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp
index c4114ad5ffa..f3d70a5734a 100644
--- a/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/ndb/src/common/util/NdbSqlUtil.cpp
@@ -15,182 +15,169 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <NdbSqlUtil.hpp>
+#include <NdbOut.hpp>
+#include <my_sys.h>
-int
-NdbSqlUtil::char_compare(const char* s1, unsigned n1,
- const char* s2, unsigned n2, bool padded)
-{
- int c1 = 0;
- int c2 = 0;
- unsigned i = 0;
- while (i < n1 || i < n2) {
- c1 = i < n1 ? s1[i] : padded ? 0x20 : 0;
- c2 = i < n2 ? s2[i] : padded ? 0x20 : 0;
- if (c1 != c2)
- break;
- i++;
- }
- return c1 - c2;
-}
-
-bool
-NdbSqlUtil::char_like(const char* s1, unsigned n1,
- const char* s2, unsigned n2, bool padded)
-{
- int c1 = 0;
- int c2 = 0;
- unsigned i1 = 0;
- unsigned i2 = 0;
- while (i1 < n1 || i2 < n2) {
- c1 = i1 < n1 ? s1[i1] : padded ? 0x20 : 0;
- c2 = i2 < n2 ? s2[i2] : padded ? 0x20 : 0;
- if (c2 == '%') {
- while (i2 + 1 < n2 && s2[i2 + 1] == '%') {
- i2++;
- }
- unsigned m = 0;
- while (m <= n1 - i1) {
- if (char_like(s1 + i1 + m, n1 -i1 - m,
- s2 + i2 + 1, n2 - i2 - 1, padded))
- return true;
- m++;
- }
- return false;
- }
- if (c2 == '_') {
- if (c1 == 0)
- return false;
- } else {
- if (c1 != c2)
- return false;
- }
- i1++;
- i2++;
- }
- return i1 == n2 && i2 == n2;
-}
-
-/**
- * Data types.
+/*
+ * Data types. The entries must be in the numerical order.
*/
const NdbSqlUtil::Type
NdbSqlUtil::m_typeList[] = {
{ // 0
Type::Undefined,
+ NULL,
NULL
},
{ // 1
Type::Tinyint,
- cmpTinyint
+ cmpTinyint,
+ NULL
},
{ // 2
Type::Tinyunsigned,
- cmpTinyunsigned
+ cmpTinyunsigned,
+ NULL
},
{ // 3
Type::Smallint,
- cmpSmallint
+ cmpSmallint,
+ NULL
},
{ // 4
Type::Smallunsigned,
- cmpSmallunsigned
+ cmpSmallunsigned,
+ NULL
},
{ // 5
Type::Mediumint,
- cmpMediumint
+ cmpMediumint,
+ NULL
},
{ // 6
Type::Mediumunsigned,
- cmpMediumunsigned
+ cmpMediumunsigned,
+ NULL
},
{ // 7
Type::Int,
- cmpInt
+ cmpInt,
+ NULL
},
{ // 8
Type::Unsigned,
- cmpUnsigned
+ cmpUnsigned,
+ NULL
},
{ // 9
Type::Bigint,
- cmpBigint
+ cmpBigint,
+ NULL
},
{ // 10
Type::Bigunsigned,
- cmpBigunsigned
+ cmpBigunsigned,
+ NULL
},
{ // 11
Type::Float,
- cmpFloat
+ cmpFloat,
+ NULL
},
{ // 12
Type::Double,
- cmpDouble
+ cmpDouble,
+ NULL
},
{ // 13
Type::Olddecimal,
- cmpOlddecimal
+ cmpOlddecimal,
+ NULL
},
{ // 14
Type::Char,
- cmpChar
+ cmpChar,
+ likeChar
},
{ // 15
Type::Varchar,
- cmpVarchar
+ cmpVarchar,
+ likeVarchar
},
{ // 16
Type::Binary,
- cmpBinary
+ cmpBinary,
+ likeBinary
},
{ // 17
Type::Varbinary,
- cmpVarbinary
+ cmpVarbinary,
+ likeVarbinary
},
{ // 18
Type::Datetime,
- cmpDatetime
+ cmpDatetime,
+ NULL
},
{ // 19
Type::Date,
- cmpDate
+ cmpDate,
+ NULL
},
{ // 20
Type::Blob,
- cmpBlob
+ NULL,
+ NULL
},
{ // 21
Type::Text,
- cmpText
+ NULL,
+ NULL
},
{ // 22
- Type::Undefined, // 5.0 Bit
+ Type::Bit,
+ NULL,
NULL
},
{ // 23
- Type::Undefined, // 5.0 Longvarchar
- NULL
+ Type::Longvarchar,
+ cmpLongvarchar,
+ likeLongvarchar
},
{ // 24
- Type::Undefined, // 5.0 Longvarbinary
- NULL
+ Type::Longvarbinary,
+ cmpLongvarbinary,
+ likeLongvarbinary
},
{ // 25
Type::Time,
- cmpTime
+ cmpTime,
+ NULL
},
{ // 26
Type::Year,
- cmpYear
+ cmpYear,
+ NULL
},
{ // 27
Type::Timestamp,
- cmpTimestamp
+ cmpTimestamp,
+ NULL
},
{ // 28
Type::Olddecimalunsigned,
- cmpOlddecimalunsigned
+ cmpOlddecimalunsigned,
+ NULL
+ },
+ { // 29
+ Type::Decimal,
+ cmpDecimal,
+ NULL
+ },
+ { // 30
+ Type::Decimalunsigned,
+ cmpDecimalunsigned,
+ NULL
}
};
@@ -209,10 +196,12 @@ NdbSqlUtil::getTypeBinary(Uint32 typeId)
{
switch (typeId) {
case Type::Char:
- typeId = Type::Binary;
- break;
case Type::Varchar:
- typeId = Type::Varbinary;
+ case Type::Binary:
+ case Type::Varbinary:
+ case Type::Longvarchar:
+ case Type::Longvarbinary:
+ typeId = Type::Binary;
break;
case Type::Text:
typeId = Type::Blob;
@@ -223,194 +212,211 @@ NdbSqlUtil::getTypeBinary(Uint32 typeId)
return getType(typeId);
}
-// compare
+/*
+ * Comparison functions.
+ */
int
-NdbSqlUtil::cmpTinyint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpTinyint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Int8 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int8)) {
+ Int8 v1, v2;
+ memcpy(&v1, p1, sizeof(Int8));
+ memcpy(&v2, p2, sizeof(Int8));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpTinyunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpTinyunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint8 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint8)) {
+ Uint8 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint8));
+ memcpy(&v2, p2, sizeof(Uint8));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpSmallint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpSmallint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Int16 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int16)) {
+ Int16 v1, v2;
+ memcpy(&v1, p1, sizeof(Int16));
+ memcpy(&v2, p2, sizeof(Int16));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpSmallunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpSmallunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint16 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint16)) {
+ Uint16 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint16));
+ memcpy(&v2, p2, sizeof(Uint16));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpMediumint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpMediumint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- 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;
+ if (n2 >= 3) {
+ Int32 v1, v2;
+ v1 = sint3korr((const uchar*)p1);
+ v2 = sint3korr((const uchar*)p2);
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpMediumunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpMediumunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- 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;
+ if (n2 >= 3) {
+ Uint32 v1, v2;
+ v1 = uint3korr((const uchar*)p1);
+ v2 = uint3korr((const uchar*)p2);
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpInt(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpInt(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Int32 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int32)) {
+ Int32 v1, v2;
+ memcpy(&v1, p1, sizeof(Int32));
+ memcpy(&v2, p2, sizeof(Int32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpUnsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpUnsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint32 v; } u1, u2;
- u1.v = p1[0];
- u2.v = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint32)) {
+ Uint32 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint32));
+ memcpy(&v2, p2, sizeof(Uint32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpBigint(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBigint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; Int64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
+ if (n2 >= sizeof(Int64)) {
+ Int64 v1, v2;
+ memcpy(&v1, p1, sizeof(Int64));
+ memcpy(&v2, p2, sizeof(Int64));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpBigunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBigunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; Uint64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
+ if (n2 >= sizeof(Uint64)) {
+ Uint64 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint64));
+ memcpy(&v2, p2, sizeof(Uint64));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpFloat(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpFloat(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; float v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- // no format check
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(float)) {
+ float v1, v2;
+ memcpy(&v1, p1, sizeof(float));
+ memcpy(&v2, p2, sizeof(float));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpDouble(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDouble(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; double v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- // no format check
- if (u1.v < u2.v)
+ if (n2 >= sizeof(double)) {
+ double v1, v2;
+ memcpy(&v1, p1, sizeof(double));
+ memcpy(&v2, p2, sizeof(double));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
@@ -440,407 +446,568 @@ NdbSqlUtil::cmp_olddecimal(const uchar* s1, const uchar* s2, unsigned n)
}
int
-NdbSqlUtil::cmpOlddecimal(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpOlddecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (full == size) {
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- return cmp_olddecimal(u1.v, u2.v, full << 2);
+ if (full) {
+ assert(n1 == n2);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ return cmp_olddecimal(v1, v2, n1);
}
return CmpUnknown;
}
int
-NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (full == size) {
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- return cmp_olddecimal(u1.v, u2.v, full << 2);
+ if (full) {
+ assert(n1 == n2);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ return cmp_olddecimal(v1, v2, n1);
}
return CmpUnknown;
}
int
-NdbSqlUtil::cmpChar(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // compare as binary strings
+ unsigned n = (n1 <= n2 ? n1 : n2);
+ int k = memcmp(v1, v2, n);
+ if (k == 0) {
+ k = (full ? n1 : n) - n2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+}
+
+int
+NdbSqlUtil::cmpDecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // compare as binary strings
+ unsigned n = (n1 <= n2 ? n1 : n2);
+ int k = memcmp(v1, v2, n);
+ if (k == 0) {
+ k = (full ? n1 : n) - n2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+}
+
+int
+NdbSqlUtil::cmpChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
// collation does not work on prefix for some charsets
- assert(full == size && size > 0);
- /*
- * Char is blank-padded to length and null-padded to word size.
- */
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
+ assert(full);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
// not const in MySQL
CHARSET_INFO* cs = (CHARSET_INFO*)(info);
- // length in bytes including null padding to Uint32
- uint l1 = (full << 2);
- int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+ // compare with space padding
+ int k = (*cs->coll->strnncollsp)(cs, v1, n1, v2, n2, false);
return k < 0 ? -1 : k > 0 ? +1 : 0;
}
int
-NdbSqlUtil::cmpVarchar(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- /*
- * Varchar is not allowed to contain a null byte and the value is
- * null-padded. Therefore comparison does not need to use the length.
- *
- * Not used before MySQL 5.0. Format is likely to change. Handle
- * only binary collation for now.
- */
- union { const Uint32* p; const char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- // skip length in first 2 bytes
- int k = strncmp(u1.v + 2, u2.v + 2, (size << 2) - 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ const unsigned lb = 1;
+ // collation does not work on prefix for some charsets
+ assert(full && n1 >= lb && n2 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = *v1;
+ unsigned m2 = *v2;
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ // compare with space padding
+ int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
+ return k < 0 ? -1 : k > 0 ? +1 : 0;
+ }
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
}
int
-NdbSqlUtil::cmpBinary(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
-{
- assert(full >= size && size > 0);
- /*
- * Binary data of full length. Compare bytewise.
- */
- union { const Uint32* p; const unsigned 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;
+NdbSqlUtil::cmpBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // compare as binary strings
+ unsigned n = (n1 <= n2 ? n1 : n2);
+ int k = memcmp(v1, v2, n);
+ if (k == 0) {
+ k = (full ? n1 : n) - n2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
}
int
-NdbSqlUtil::cmpVarbinary(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
-{
- assert(full >= size && size > 0);
- /*
- * Binary data of variable length padded with nulls. The comparison
- * does not need to use the length.
- *
- * Not used before MySQL 5.0. Format is likely to change.
- */
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- // skip 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;
+NdbSqlUtil::cmpVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const unsigned lb = 1;
+ if (n2 >= lb) {
+ assert(n1 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = *v1;
+ unsigned m2 = *v2;
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
+ // compare as binary strings
+ unsigned m = (m1 <= m2 ? m1 : m2);
+ int k = memcmp(v1 + lb, v2 + lb, m);
+ if (k == 0) {
+ k = (full ? m1 : m) - m2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+ }
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpDatetime(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDatetime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- if (size >= 2) {
- union { Uint32 p[2]; Int64 v; } u1, u2;
- u1.p[0] = p1[0];
- u1.p[1] = p1[1];
- u2.p[0] = p2[0];
- u2.p[1] = p2[1];
- if (u1.v < u2.v)
+ if (n2 >= sizeof(Int64)) {
+ Int64 v1, v2;
+ memcpy(&v1, p1, sizeof(Int64));
+ memcpy(&v2, p2, sizeof(Int64));
+ if (v1 < v2)
return -1;
- if (u1.v > u2.v)
+ if (v1 > v2)
return +1;
return 0;
}
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpDate(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
#ifdef ndb_date_is_4_byte_native_int
- assert(full >= size && size > 0);
- union { Uint32 p[2]; Int32 v; } u1, u2;
- u1.p[0] = p1[0];
- u2.p[0] = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ if (n2 >= sizeof(Int32)) {
+ Int32 v1, v2;
+ memcpy(&v1, p1, sizeof(Int32));
+ memcpy(&v2, p2, sizeof(Int32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
#else
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
#ifdef ndb_date_sol9x86_cc_xO3_madness
- // from Field_newdate::val_int
- Uint64 j1 = uint3korr(u1.v);
- Uint64 j2 = uint3korr(u2.v);
- j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
- j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
- if (j1 < j2)
- return -1;
- if (j1 > j2)
- return +1;
- return 0;
+ if (n2 >= 3) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // from Field_newdate::val_int
+ Uint64 j1 = uint3korr(v1);
+ Uint64 j2 = uint3korr(v2);
+ j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
+ j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
+ if (j1 < j2)
+ return -1;
+ if (j1 > j2)
+ return +1;
+ return 0;
+ }
#else
- uint j1 = uint3korr(u1.v);
- uint j2 = uint3korr(u2.v);
- uint d1 = (j1 & 31);
- uint d2 = (j2 & 31);
- j1 = (j1 >> 5);
- j2 = (j2 >> 5);
- uint m1 = (j1 & 15);
- uint m2 = (j2 & 15);
- j1 = (j1 >> 4);
- j2 = (j2 >> 4);
- uint y1 = j1;
- uint y2 = j2;
- if (y1 < y2)
- return -1;
- if (y1 > y2)
- return +1;
- if (m1 < m2)
- return -1;
- if (m1 > m2)
- return +1;
- if (d1 < d2)
- return -1;
- if (d1 > d2)
- return +1;
- return 0;
+ if (n2 >= 3) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ uint j1 = uint3korr(v1);
+ uint j2 = uint3korr(v2);
+ uint d1 = (j1 & 31);
+ uint d2 = (j2 & 31);
+ j1 = (j1 >> 5);
+ j2 = (j2 >> 5);
+ uint m1 = (j1 & 15);
+ uint m2 = (j2 & 15);
+ j1 = (j1 >> 4);
+ j2 = (j2 >> 4);
+ uint y1 = j1;
+ uint y2 = j2;
+ if (y1 < y2)
+ return -1;
+ if (y1 > y2)
+ return +1;
+ if (m1 < m2)
+ return -1;
+ if (m1 > m2)
+ return +1;
+ if (d1 < d2)
+ return -1;
+ if (d1 > d2)
+ return +1;
+ return 0;
+ }
#endif
#endif
+ assert(! full);
+ return CmpUnknown;
}
+// not supported
int
-NdbSqlUtil::cmpBlob(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBlob(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- /*
- * Blob comparison is on the inline bytes (null padded).
- */
- const unsigned head = NDB_BLOB_HEAD_SIZE;
- // skip blob head
- if (size >= head + 1) {
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1 + head;
- u2.p = p2 + head;
- int k = memcmp(u1.v, u2.v, (size - head) << 2);
- return k < 0 ? -1 : k > 0 ? +1 : full == size ? 0 : CmpUnknown;
+ assert(false);
+ return 0;
+}
+
+// not supported
+int
+NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ assert(false);
+ return 0;
+}
+
+int
+NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ if (n2 >= 3) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ // from Field_time::val_int
+ Int32 j1 = sint3korr(v1);
+ Int32 j2 = sint3korr(v2);
+ if (j1 < j2)
+ return -1;
+ if (j1 > j2)
+ return +1;
+ return 0;
}
+ assert(! full);
return CmpUnknown;
}
+// not yet
int
-NdbSqlUtil::cmpText(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
+ assert(false);
+ return 0;
+}
+
+int
+NdbSqlUtil::cmpLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const unsigned lb = 2;
// collation does not work on prefix for some charsets
- assert(full == size && size > 0);
- /*
- * Text comparison is on the inline bytes (blank padded). Currently
- * not supported for multi-byte charsets.
- */
- const unsigned head = NDB_BLOB_HEAD_SIZE;
- // skip blob head
- if (size >= head + 1) {
- union { const Uint32* p; const uchar* v; } u1, u2;
- u1.p = p1 + head;
- u2.p = p2 + head;
- // not const in MySQL
+ assert(full && n1 >= lb && n2 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = uint2korr(v1);
+ unsigned m2 = uint2korr(v2);
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
CHARSET_INFO* cs = (CHARSET_INFO*)(info);
- // length in bytes including null padding to Uint32
- uint l1 = (full << 2);
- int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+ // compare with space padding
+ int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
return k < 0 ? -1 : k > 0 ? +1 : 0;
}
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
+}
+
+int
+NdbSqlUtil::cmpLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
+{
+ const unsigned lb = 2;
+ if (n2 >= lb) {
+ assert(n1 >= lb);
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = uint2korr(v1);
+ unsigned m2 = uint2korr(v2);
+ if (m1 <= n1 - lb && m2 <= n2 - lb) {
+ // compare as binary strings
+ unsigned m = (m1 <= m2 ? m1 : m2);
+ int k = memcmp(v1 + lb, v2 + lb, m);
+ if (k == 0) {
+ k = (full ? m1 : m) - m2;
+ }
+ return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
+ }
+ // treat bad data as NULL
+ if (m1 > n1 - lb && m2 <= n2 - lb)
+ return -1;
+ if (m1 <= n1 - lb && m2 > n2 - lb)
+ return +1;
+ return 0;
+ }
+ assert(! full);
return CmpUnknown;
}
int
-NdbSqlUtil::cmpTime(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpYear(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- // from Field_time::val_int
- Int32 j1 = sint3korr(u1.v);
- Int32 j2 = sint3korr(u2.v);
- if (j1 < j2)
- return -1;
- if (j1 > j2)
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint8)) {
+ Uint8 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint8));
+ memcpy(&v2, p2, sizeof(Uint8));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
int
-NdbSqlUtil::cmpYear(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::cmpTimestamp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
- assert(full >= size && size > 0);
- union { const Uint32* p; const unsigned char* v; } u1, u2;
- u1.p = p1;
- u2.p = p2;
- if (u1.v[0] < u2.v[0])
- return -1;
- if (u1.v[0] > u2.v[0])
- return +1;
- return 0;
+ if (n2 >= sizeof(Uint32)) {
+ Uint32 v1, v2;
+ memcpy(&v1, p1, sizeof(Uint32));
+ memcpy(&v2, p2, sizeof(Uint32));
+ if (v1 < v2)
+ return -1;
+ if (v1 > v2)
+ return +1;
+ return 0;
+ }
+ assert(! full);
+ return CmpUnknown;
}
+// like
+
+static const int ndb_wild_prefix = '\\';
+static const int ndb_wild_one = '_';
+static const int ndb_wild_many = '%';
+
int
-NdbSqlUtil::cmpTimestamp(const void* info, const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size)
+NdbSqlUtil::likeChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
- assert(full >= size && size > 0);
- union { Uint32 p[1]; Uint32 v; } u1, u2;
- u1.v = p1[0];
- u2.v = p2[0];
- if (u1.v < u2.v)
- return -1;
- if (u1.v > u2.v)
- return +1;
- return 0;
+ const char* v1 = (const char*)p1;
+ const char* v2 = (const char*)p2;
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ // strip end spaces to match (incorrect) MySQL behaviour
+ n1 = (*cs->cset->lengthsp)(cs, v1, n1);
+ int k = (*cs->coll->wildcmp)(cs, v1, v1 + n1, v2, v2 + n2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
+ return k == 0 ? 0 : +1;
+}
+
+int
+NdbSqlUtil::likeBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ assert(info == 0);
+ return likeChar(&my_charset_bin, p1, n1, p2, n2);
+}
+
+int
+NdbSqlUtil::likeVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ const unsigned lb = 1;
+ if (n1 >= lb) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = *v1;
+ unsigned m2 = n2;
+ if (lb + m1 <= n1) {
+ const char* w1 = (const char*)v1 + lb;
+ const char* w2 = (const char*)v2;
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
+ return k == 0 ? 0 : +1;
+ }
+ }
+ return -1;
+}
+
+int
+NdbSqlUtil::likeVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ assert(info == 0);
+ return likeVarchar(&my_charset_bin, p1, n1, p2, n2);
+}
+
+int
+NdbSqlUtil::likeLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ const unsigned lb = 2;
+ if (n1 >= lb) {
+ const uchar* v1 = (const uchar*)p1;
+ const uchar* v2 = (const uchar*)p2;
+ unsigned m1 = uint2korr(v1);
+ unsigned m2 = n2;
+ if (lb + m1 <= n1) {
+ const char* w1 = (const char*)v1 + lb;
+ const char* w2 = (const char*)v2;
+ CHARSET_INFO* cs = (CHARSET_INFO*)(info);
+ int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
+ return k == 0 ? 0 : +1;
+ }
+ }
+ return -1;
+}
+
+int
+NdbSqlUtil::likeLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
+{
+ assert(info == 0);
+ return likeLongvarchar(&my_charset_bin, p1, n1, p2, n2);
}
// check charset
-bool
-NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info)
+uint
+NdbSqlUtil::check_column_for_pk(Uint32 typeId, const void* info)
{
const Type& type = getType(typeId);
switch (type.m_typeId) {
- case Type::Undefined:
- break;
case Type::Char:
+ case Type::Varchar:
+ case Type::Longvarchar:
{
const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
- return
- cs != 0 &&
- cs->cset != 0 &&
- cs->coll != 0 &&
- cs->coll->strnxfrm != 0 &&
- cs->strxfrm_multiply <= 1; // current limitation
+ if(cs != 0 &&
+ cs->cset != 0 &&
+ cs->coll != 0 &&
+ cs->coll->strnxfrm != 0 &&
+ cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
+ return 0;
+ else
+ return 743;
}
break;
- case Type::Varchar:
- return true; // Varchar not used via MySQL
+ case Type::Undefined:
case Type::Blob:
case Type::Text:
+ case Type::Bit:
break;
default:
- return true;
+ return 0;
}
- return false;
+ return 906;
}
-bool
-NdbSqlUtil::usable_in_hash_index(Uint32 typeId, const void* info)
+uint
+NdbSqlUtil::check_column_for_hash_index(Uint32 typeId, const void* info)
{
- return usable_in_pk(typeId, info);
+ return check_column_for_pk(typeId, info);
}
-bool
-NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
+uint
+NdbSqlUtil::check_column_for_ordered_index(Uint32 typeId, const void* info)
{
const Type& type = getType(typeId);
+ if (type.m_cmp == NULL)
+ return false;
switch (type.m_typeId) {
- case Type::Undefined:
- break;
case Type::Char:
+ case Type::Varchar:
+ case Type::Longvarchar:
{
const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
- return
- cs != 0 &&
- cs->cset != 0 &&
- cs->coll != 0 &&
- cs->coll->strnxfrm != 0 &&
- cs->coll->strnncollsp != 0 &&
- cs->strxfrm_multiply <= 1; // current limitation
+ if (cs != 0 &&
+ cs->cset != 0 &&
+ cs->coll != 0 &&
+ cs->coll->strnxfrm != 0 &&
+ cs->coll->strnncollsp != 0 &&
+ cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
+ return 0;
+ else
+ return 743;
}
break;
- case Type::Varchar:
- return true; // Varchar not used via MySQL
+ case Type::Undefined:
+ case Type::Blob:
case Type::Text:
- {
- const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
- return
- cs != 0 &&
- cs->mbmaxlen == 1 && // extra limitation
- cs->cset != 0 &&
- cs->coll != 0 &&
- cs->coll->strnxfrm != 0 &&
- cs->coll->strnncollsp != 0 &&
- cs->strxfrm_multiply <= 1; // current limitation
+ case Type::Bit: // can be fixed
+ break;
+ default:
+ return 0;
+ }
+ return 906;
+}
+
+// utilities
+
+bool
+NdbSqlUtil::get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len)
+{
+ const unsigned char* const src = (const unsigned char*)p;
+ switch (typeId) {
+ case NdbSqlUtil::Type::Varchar:
+ case NdbSqlUtil::Type::Varbinary:
+ lb = 1;
+ if (attrlen >= lb) {
+ len = src[0];
+ if (attrlen >= lb + len)
+ return true;
+ }
+ break;
+ case NdbSqlUtil::Type::Longvarchar:
+ case NdbSqlUtil::Type::Longvarbinary:
+ lb = 2;
+ if (attrlen >= lb) {
+ len = src[0] + (src[1] << 8);
+ if (attrlen >= lb + len)
+ return true;
}
break;
default:
+ lb = 0;
+ len = attrlen;
return true;
+ break;
}
return false;
}
-#ifdef NDB_SQL_UTIL_TEST
-
-#include <NdbTick.h>
-#include <NdbOut.hpp>
-
-struct Testcase {
- int op; // 1=compare 2=like
- int res;
- const char* s1;
- const char* s2;
- int pad;
-};
-const Testcase testcase[] = {
- { 2, 1, "abc", "abc", 0 },
- { 2, 1, "abc", "abc%", 0 },
- { 2, 1, "abcdef", "abc%", 0 },
- { 2, 1, "abcdefabcdefabcdef", "abc%", 0 },
- { 2, 1, "abcdefabcdefabcdef", "abc%f", 0 },
- { 2, 0, "abcdefabcdefabcdef", "abc%z", 0 },
- { 2, 1, "abcdefabcdefabcdef", "%f", 0 },
- { 2, 1, "abcdef", "a%b%c%d%e%f", 0 },
- { 0, 0, 0, 0 }
-};
+// workaround
int
-main(int argc, char** argv)
-{
- ndb_init(); // for charsets
- unsigned count = argc > 1 ? atoi(argv[1]) : 1000000;
- ndbout_c("count = %u", count);
- assert(count != 0);
- for (const Testcase* t = testcase; t->s1 != 0; t++) {
- ndbout_c("%d = '%s' %s '%s' pad=%d",
- t->res, t->s1, t->op == 1 ? "comp" : "like", t->s2);
- NDB_TICKS x1 = NdbTick_CurrentMillisecond();
- unsigned n1 = strlen(t->s1);
- unsigned n2 = strlen(t->s2);
- for (unsigned i = 0; i < count; i++) {
- if (t->op == 1) {
- int res = NdbSqlUtil::char_compare(t->s1, n1, t->s2, n2, t->pad);
- assert(res == t->res);
- continue;
- }
- if (t->op == 2) {
- int res = NdbSqlUtil::char_like(t->s1, n1, t->s2, n2, t->pad);
- assert(res == t->res);
- continue;
- }
- assert(false);
- }
- NDB_TICKS x2 = NdbTick_CurrentMillisecond();
- if (x2 < x1)
- x2 = x1;
- double usec = 1000000.0 * double(x2 - x1) / double(count);
- ndbout_c("time %.0f usec per call", usec);
- }
- // quick check
- for (unsigned i = 0; i < sizeof(m_typeList) / sizeof(m_typeList[0]); i++) {
- const NdbSqlUtil::Type& t = m_typeList[i];
- assert(t.m_typeId == i);
+NdbSqlUtil::strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen)
+{
+ unsigned char nsp[20]; // native space char
+ unsigned char xsp[20]; // strxfrm-ed space char
+#ifdef VM_TRACE
+ memset(nsp, 0x1f, sizeof(nsp));
+ memset(xsp, 0x1f, sizeof(xsp));
+#endif
+ // convert from unicode codepoint for space
+ int n1 = (*cs->cset->wc_mb)(cs, (my_wc_t)0x20, nsp, nsp + sizeof(nsp));
+ if (n1 <= 0)
+ return -1;
+ // strxfrm to binary
+ int n2 = (*cs->coll->strnxfrm)(cs, xsp, sizeof(xsp), nsp, n1);
+ if (n2 <= 0)
+ return -1;
+ // XXX bug workaround - strnxfrm may not write full string
+ memset(dst, 0x0, dstLen);
+ // strxfrm argument string - returns no error indication
+ int n3 = (*cs->coll->strnxfrm)(cs, dst, dstLen, src, srcLen);
+ // pad with strxfrm-ed space chars
+ int n4 = n3;
+ while (n4 < (int)dstLen) {
+ dst[n4] = xsp[(n4 - n3) % n2];
+ n4++;
}
- return 0;
+ // no check for partial last
+ return dstLen;
}
-
-#endif
diff --git a/ndb/src/common/util/Parser.cpp b/ndb/src/common/util/Parser.cpp
index d692aa18392..3a86ae8f318 100644
--- a/ndb/src/common/util/Parser.cpp
+++ b/ndb/src/common/util/Parser.cpp
@@ -20,7 +20,6 @@
#include "Parser.hpp"
#include <NdbOut.hpp>
#include <Properties.hpp>
-#include <Base64.hpp>
#undef DEBUG
#define DEBUG(x) ndbout << x << endl;
@@ -316,11 +315,7 @@ ParserImpl::parseArg(Context * ctx,
}
case DummyRow::Properties: {
- Properties *sp = new Properties();
- BaseString v(value);
- UtilBuffer b;
- base64_decode(v, b);
- sp->unpack((const Uint32 *)b.get_data(), b.length());
+ abort();
break;
}
default:
diff --git a/ndb/src/common/util/SimpleProperties.cpp b/ndb/src/common/util/SimpleProperties.cpp
index 00c440fcb4e..c9251c6a854 100644
--- a/ndb/src/common/util/SimpleProperties.cpp
+++ b/ndb/src/common/util/SimpleProperties.cpp
@@ -37,6 +37,29 @@ SimpleProperties::Writer::add(Uint16 key, Uint32 value){
}
bool
+SimpleProperties::Writer::add(const char * value, int len){
+ const Uint32 valLen = (len + 3) / 4;
+
+ if ((len % 4) == 0)
+ return putWords((Uint32*)value, valLen);
+
+ const Uint32 putLen= valLen - 1;
+ if (!putWords((Uint32*)value, putLen))
+ return false;
+
+ // Special handling of last bytes
+ union {
+ Uint32 lastWord;
+ char lastBytes[4];
+ } tmp;
+ tmp.lastWord =0 ;
+ memcpy(tmp.lastBytes,
+ value + putLen*4,
+ len - putLen*4);
+ return putWord(tmp.lastWord);
+}
+
+bool
SimpleProperties::Writer::add(Uint16 key, const char * value){
Uint32 head = StringValue;
head <<= 16;
@@ -46,9 +69,9 @@ SimpleProperties::Writer::add(Uint16 key, const char * value){
Uint32 strLen = strlen(value) + 1; // Including NULL-byte
if(!putWord(htonl(strLen)))
return false;
-
- const Uint32 valLen = (strLen + 3) / 4;
- return putWords((Uint32*)value, valLen);
+
+ return add(value, (int)strLen);
+
}
bool
@@ -60,9 +83,8 @@ SimpleProperties::Writer::add(Uint16 key, const void* value, int len){
return false;
if(!putWord(htonl(len)))
return false;
-
- const Uint32 valLen = (len + 3) / 4;
- return putWords((Uint32*)value, valLen);
+
+ return add((const char*)value, len);
}
SimpleProperties::Reader::Reader(){
@@ -392,6 +414,7 @@ UtilBufferWriter::putWords(const Uint32 * src, Uint32 len){
return (m_buf.append(src, 4 * len) == 0);
}
+
Uint32
UtilBufferWriter::getWordsUsed() const { return m_buf.length() / 4;}
diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp
index 755764c7700..f9d2c7463be 100644
--- a/ndb/src/common/util/SocketServer.cpp
+++ b/ndb/src/common/util/SocketServer.cpp
@@ -42,6 +42,8 @@ SocketServer::~SocketServer() {
delete m_sessions[i].m_session;
}
for(i = 0; i<m_services.size(); i++){
+ if(m_services[i].m_socket)
+ NDB_CLOSE_SOCKET(m_services[i].m_socket);
delete m_services[i].m_service;
}
}
@@ -84,15 +86,15 @@ SocketServer::tryBind(unsigned short port, const char * intface) {
bool
SocketServer::setup(SocketServer::Service * service,
- unsigned short port,
+ unsigned short * port,
const char * intface){
DBUG_ENTER("SocketServer::setup");
- DBUG_PRINT("enter",("interface=%s, port=%d", intface, port));
+ DBUG_PRINT("enter",("interface=%s, port=%u", intface, *port));
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servaddr.sin_port = htons(port);
+ servaddr.sin_port = htons(*port);
if(intface != 0){
if(Ndb_getInAddr(&servaddr.sin_addr, intface))
@@ -123,7 +125,17 @@ SocketServer::setup(SocketServer::Service * service,
NDB_CLOSE_SOCKET(sock);
DBUG_RETURN(false);
}
-
+
+ /* Get the port we bound to */
+ SOCKET_SIZE_TYPE sock_len = sizeof(servaddr);
+ if(getsockname(sock,(struct sockaddr*)&servaddr,&sock_len)<0) {
+ ndbout_c("An error occurred while trying to find out what"
+ " port we bound to. Error: %s",strerror(errno));
+ NDB_CLOSE_SOCKET(sock);
+ DBUG_RETURN(false);
+ }
+
+ DBUG_PRINT("info",("bound to %u",ntohs(servaddr.sin_port)));
if (listen(sock, m_maxSessions > 32 ? 32 : m_maxSessions) == -1){
DBUG_PRINT("error",("listen() - %d - %s",
errno, strerror(errno)));
@@ -135,6 +147,9 @@ SocketServer::setup(SocketServer::Service * service,
i.m_socket = sock;
i.m_service = service;
m_services.push_back(i);
+
+ *port = ntohs(servaddr.sin_port);
+
DBUG_RETURN(true);
}
@@ -169,9 +184,12 @@ SocketServer::doAccept(){
SessionInstance s;
s.m_service = si.m_service;
s.m_session = si.m_service->newSession(childSock);
- if(s.m_session != 0){
+ if(s.m_session != 0)
+ {
+ m_session_mutex.lock();
m_sessions.push_back(s);
startSession(m_sessions.back());
+ m_session_mutex.unlock();
}
continue;
@@ -225,10 +243,13 @@ void
SocketServer::doRun(){
while(!m_stopThread){
- checkSessions();
+ m_session_mutex.lock();
+ checkSessionsImpl();
if(m_sessions.size() < m_maxSessions){
+ m_session_mutex.unlock();
doAccept();
} else {
+ m_session_mutex.unlock();
NdbSleep_MilliSleep(200);
}
}
@@ -261,17 +282,30 @@ transfer(NDB_SOCKET_TYPE sock){
void
SocketServer::foreachSession(void (*func)(SocketServer::Session*, void *), void *data)
{
+ m_session_mutex.lock();
for(int i = m_sessions.size() - 1; i >= 0; i--){
(*func)(m_sessions[i].m_session, data);
}
- checkSessions();
+ m_session_mutex.unlock();
}
void
-SocketServer::checkSessions(){
- for(int i = m_sessions.size() - 1; i >= 0; i--){
- if(m_sessions[i].m_session->m_stopped){
- if(m_sessions[i].m_thread != 0){
+SocketServer::checkSessions()
+{
+ m_session_mutex.lock();
+ checkSessionsImpl();
+ m_session_mutex.unlock();
+}
+
+void
+SocketServer::checkSessionsImpl()
+{
+ for(int i = m_sessions.size() - 1; i >= 0; i--)
+ {
+ if(m_sessions[i].m_session->m_stopped)
+ {
+ if(m_sessions[i].m_thread != 0)
+ {
void* ret;
NdbThread_WaitFor(m_sessions[i].m_thread, &ret);
NdbThread_Destroy(&m_sessions[i].m_thread);
@@ -286,19 +320,26 @@ SocketServer::checkSessions(){
void
SocketServer::stopSessions(bool wait){
int i;
+ m_session_mutex.lock();
for(i = m_sessions.size() - 1; i>=0; i--)
{
m_sessions[i].m_session->stopSession();
m_sessions[i].m_session->m_stop = true; // to make sure
}
+ m_session_mutex.unlock();
+
for(i = m_services.size() - 1; i>=0; i--)
m_services[i].m_service->stopSessions();
if(wait){
+ m_session_mutex.lock();
while(m_sessions.size() > 0){
- checkSessions();
+ checkSessionsImpl();
+ m_session_mutex.unlock();
NdbSleep_MilliSleep(100);
+ m_session_mutex.lock();
}
+ m_session_mutex.unlock();
}
}
@@ -314,11 +355,18 @@ sessionThread_C(void* _sc){
return 0;
}
- if(!si->m_stop){
- si->m_stopped = false;
- si->runSession();
- } else {
- NDB_CLOSE_SOCKET(si->m_socket);
+ /**
+ * may have m_stopped set if we're transforming a mgm
+ * connection into a transporter connection.
+ */
+ if(!si->m_stopped)
+ {
+ if(!si->m_stop){
+ si->m_stopped = false;
+ si->runSession();
+ } else {
+ NDB_CLOSE_SOCKET(si->m_socket);
+ }
}
si->m_stopped = true;
@@ -326,4 +374,4 @@ sessionThread_C(void* _sc){
}
template class MutexVector<SocketServer::ServiceInstance>;
-template class MutexVector<SocketServer::SessionInstance>;
+template class Vector<SocketServer::SessionInstance>;
diff --git a/ndb/src/common/util/md5_hash.cpp b/ndb/src/common/util/md5_hash.cpp
index 068843183ac..d4eedbc40fb 100644
--- a/ndb/src/common/util/md5_hash.cpp
+++ b/ndb/src/common/util/md5_hash.cpp
@@ -75,7 +75,7 @@ void byteReverse(unsigned char *buf, unsigned longs)
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
-void MD5Transform(Uint32 buf[4], Uint32 const in[16])
+static void MD5Transform(Uint32 buf[4], Uint32 const in[16])
{
register Uint32 a, b, c, d;
@@ -162,13 +162,13 @@ void MD5Transform(Uint32 buf[4], Uint32 const in[16])
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words)
{
-/*
- * This is the external interface of the module
- * It is assumed that keybuf is placed on 8 byte
- * alignment.
- */
+ /**
+ * This is the external interface of the module
+ * It is assumed that keybuf is placed on 8 byte
+ * alignment.
+ */
Uint32 i;
Uint32 buf[4];
Uint64 transform64_buf[8];
@@ -230,6 +230,10 @@ Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
byteReverse((unsigned char *)transform32_buf, 16);
MD5Transform(buf, transform32_buf);
}
- return buf[0];
+
+ result[0] = buf[0];
+ result[1] = buf[1];
+ result[2] = buf[2];
+ result[3] = buf[3];
}
diff --git a/ndb/src/common/util/new.cpp b/ndb/src/common/util/new.cpp
index 901f74bf979..643800f1582 100644
--- a/ndb/src/common/util/new.cpp
+++ b/ndb/src/common/util/new.cpp
@@ -6,7 +6,7 @@ extern "C" {
void (* ndb_new_handler)() = 0;
}
-#ifdef USE_MYSYS_NEW
+#if 0
void *operator new (size_t sz)
{
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index 83a546de773..58636e6663d 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -48,58 +48,66 @@ read_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
extern "C"
int
-readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
+readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
char * buf, int buflen){
if(buflen <= 1)
return 0;
+ int sock_flags= fcntl(socket, F_GETFL);
+ if(fcntl(socket, F_SETFL, sock_flags | O_NONBLOCK) == -1)
+ return -1;
+
fd_set readset;
FD_ZERO(&readset);
FD_SET(socket, &readset);
-
+
struct timeval timeout;
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 == 0)
+ if(selectRes == 0){
return 0;
-
+ }
+
if(selectRes == -1){
+ fcntl(socket, F_SETFL, sock_flags);
return -1;
}
-
- int pos = 0; buf[pos] = 0;
- while(true){
- const int t = recv(socket, &buf[pos], 1, 0);
- if(t != 1){
- return -1;
- }
- if(buf[pos] == '\n'){
- buf[pos] = 0;
- if(pos > 0 && buf[pos-1] == '\r'){
- pos--;
- buf[pos] = 0;
+ buf[0] = 0;
+ const int t = recv(socket, buf, buflen, MSG_PEEK);
+
+ if(t < 1)
+ {
+ fcntl(socket, F_SETFL, sock_flags);
+ return -1;
+ }
+
+ for(int i=0; i< t;i++)
+ {
+ if(buf[i] == '\n'){
+ recv(socket, buf, i+1, 0);
+ buf[i] = 0;
+
+ if(i > 0 && buf[i-1] == '\r'){
+ i--;
+ buf[i] = 0;
}
- return pos;
- }
- pos++;
- if(pos == (buflen - 1)){
- buf[pos] = 0;
- return buflen;
- }
-
- FD_ZERO(&readset);
- FD_SET(socket, &readset);
- 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;
+ fcntl(socket, F_SETFL, sock_flags);
+ return t;
}
}
+
+ if(t == (buflen - 1)){
+ recv(socket, buf, t, 0);
+ buf[t] = 0;
+ fcntl(socket, F_SETFL, sock_flags);
+ return buflen;
+ }
+
+ return 0;
}
extern "C"
diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c
index 51cf8082a62..8076db576c2 100644
--- a/ndb/src/common/util/version.c
+++ b/ndb/src/common/util/version.c
@@ -92,6 +92,8 @@ void ndbSetOwnVersion() {}
#ifndef TEST_VERSION
struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
+ { MAKE_VERSION(5,0,NDB_VERSION_BUILD), MAKE_VERSION(5,0,12), UG_Range},
+ { MAKE_VERSION(5,0,11), MAKE_VERSION(5,0,2), UG_Range},
{ MAKE_VERSION(4,1,NDB_VERSION_BUILD), MAKE_VERSION(4,1,15), UG_Range },
{ MAKE_VERSION(4,1,14), MAKE_VERSION(4,1,10), UG_Range },
{ MAKE_VERSION(4,1,10), MAKE_VERSION(4,1,9), UG_Exact },
@@ -101,6 +103,8 @@ struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
};
struct NdbUpGradeCompatible ndbCompatibleTable_upgrade[] = {
+ { MAKE_VERSION(5,0,12), MAKE_VERSION(5,0,11), UG_Exact },
+ { MAKE_VERSION(5,0,2), MAKE_VERSION(4,1,8), UG_Exact },
{ MAKE_VERSION(4,1,15), MAKE_VERSION(4,1,14), UG_Exact },
{ MAKE_VERSION(3,5,4), MAKE_VERSION(3,5,3), UG_Exact },
{ 0, 0, UG_Null }
diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp
index b009f0c0fc4..e7a2092c15d 100644
--- a/ndb/src/cw/cpcd/APIService.cpp
+++ b/ndb/src/cw/cpcd/APIService.cpp
@@ -136,6 +136,8 @@ ParserRow<CPCDAPISession> commands[] =
CPCD_ARG("id", Int, Mandatory, "Id of process"),
CPCD_CMD("list processes", &CPCDAPISession::listProcesses, ""),
+
+ CPCD_CMD("show version", &CPCDAPISession::showVersion, ""),
CPCD_END()
};
@@ -359,6 +361,7 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
m_output->println("stdout: %s", p->m_stdout.c_str());
m_output->println("stderr: %s", p->m_stderr.c_str());
m_output->println("ulimit: %s", p->m_ulimit.c_str());
+ m_output->println("shutdown: %s", p->m_shutdown_options.c_str());
switch(p->m_status){
case STOPPED:
m_output->println("status: stopped");
@@ -384,4 +387,16 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */,
m_cpcd.m_processes.unlock();
}
+void
+CPCDAPISession::showVersion(Parser_t::Context & /* unused */,
+ const class Properties & args){
+ Uint32 id;
+ CPCD::RequestStatus rs;
+
+ m_output->println("show version");
+ m_output->println("compile time: %s %s", __DATE__, __TIME__);
+
+ m_output->println("");
+}
+
template class Vector<ParserRow<CPCDAPISession> const*>;
diff --git a/ndb/src/cw/cpcd/APIService.hpp b/ndb/src/cw/cpcd/APIService.hpp
index ef988785f89..3586d64187e 100644
--- a/ndb/src/cw/cpcd/APIService.hpp
+++ b/ndb/src/cw/cpcd/APIService.hpp
@@ -49,6 +49,7 @@ public:
void stopProcess(Parser_t::Context & ctx, const class Properties & args);
void showProcess(Parser_t::Context & ctx, const class Properties & args);
void listProcesses(Parser_t::Context & ctx, const class Properties & args);
+ void showVersion(Parser_t::Context & ctx, const class Properties & args);
};
class CPCDAPIService : public SocketServer::Service {
diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp
index ba877095a04..c320f07ef04 100644
--- a/ndb/src/cw/cpcd/main.cpp
+++ b/ndb/src/cw/cpcd/main.cpp
@@ -138,7 +138,8 @@ int main(int argc, char** argv){
SocketServer * ss = new SocketServer();
CPCDAPIService * serv = new CPCDAPIService(cpcd);
- if(!ss->setup(serv, port)){
+ unsigned short real_port= port; // correct type
+ if(!ss->setup(serv, &real_port)){
logger.critical("Cannot setup server: %s", strerror(errno));
sleep(1);
delete ss;
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index d6dfcfe8587..c8c9e82efc2 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -4,13 +4,13 @@ Next NDBFS 2000
Next DBACC 3002
Next DBTUP 4014
Next DBLQH 5043
-Next DBDICT 6006
-Next DBDIH 7174
+Next DBDICT 6007
+Next DBDIH 7177
Next DBTC 8038
Next CMVMI 9000
Next BACKUP 10022
Next DBUTIL 11002
-Next DBTUX 12007
+Next DBTUX 12008
Next SUMA 13001
TESTING NODE FAILURE, ARBITRATION
@@ -205,6 +205,8 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out.
8048: Make TC not choose own node for simple/dirty read
5041: Crash is receiving simple read from other TC on different node
+8050: Send TCKEYREF is operation is non local
+
5100,5101: Drop ABORT req in primary replica
Crash on "next" ABORT
@@ -311,6 +313,10 @@ Test Crashes in handling node restarts
7170: Crash when receiving START_PERMREF (InitialStartRequired)
+7174: Crash starting node before sending DICT_LOCK_REQ
+7175: Master sends one fake START_PERMREF (ZNODE_ALREADY_STARTING_ERROR)
+7176: Slave NR pretends master does not support DICT lock (rolling upgrade)
+
DICT:
6000 Crash during NR when receiving DICTSTARTREQ
6001 Crash during NR when receiving SCHEMA_INFO
@@ -430,6 +436,7 @@ Drop Table/Index:
8034: Fail next index create in TC
8035: Fail next trigger drop in TC
8036: Fail next index drop in TC
+6006: Crash participant in create index
4013: verify TUP tab descr before and after next DROP TABLE
@@ -463,6 +470,7 @@ Test routing of signals:
Ordered index:
--------------
+12007: Make next alloc node fail with no memory error
Dbdict:
-------
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index b23b434fcd9..43c1de5e2b3 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -72,6 +72,106 @@ static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
#define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
#define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
+void
+Backup::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ c_nodePool.setSize(MAX_NDB_NODES);
+
+ Uint32 noBackups = 0, noTables = 0, noAttribs = 0, noFrags = 0;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &m_diskless));
+ ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_BACKUPS, &noBackups);
+ // ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TABLES, &noTables));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &noTables));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_ATTRIBUTES, &noAttribs));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_FRAG_CONNECT, &noFrags));
+
+ noAttribs++; //RT 527 bug fix
+
+ c_backupPool.setSize(noBackups);
+ c_backupFilePool.setSize(3 * noBackups);
+ c_tablePool.setSize(noBackups * noTables);
+ c_attributePool.setSize(noBackups * noAttribs);
+ c_triggerPool.setSize(noBackups * 3 * noTables);
+ c_fragmentPool.setSize(noBackups * noFrags);
+
+ Uint32 szMem = 0;
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MEM, &szMem);
+ Uint32 noPages = (szMem + sizeof(Page32) - 1) / sizeof(Page32);
+ // We need to allocate an additional of 2 pages. 1 page because of a bug in
+ // ArrayPool and another one for DICTTAINFO.
+ c_pagePool.setSize(noPages + NO_OF_PAGES_META_FILE + 2);
+
+ Uint32 szDataBuf = (2 * 1024 * 1024);
+ Uint32 szLogBuf = (2 * 1024 * 1024);
+ Uint32 szWrite = 32768, maxWriteSize = (256 * 1024);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_DATA_BUFFER_MEM, &szDataBuf);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_LOG_BUFFER_MEM, &szLogBuf);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_WRITE_SIZE, &szWrite);
+ ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MAX_WRITE_SIZE, &maxWriteSize);
+
+ c_defaults.m_logBufferSize = szLogBuf;
+ c_defaults.m_dataBufferSize = szDataBuf;
+ c_defaults.m_minWriteSize = szWrite;
+ c_defaults.m_maxWriteSize = maxWriteSize;
+
+ { // Init all tables
+ ArrayList<Table> tables(c_tablePool);
+ TablePtr ptr;
+ while(tables.seize(ptr)){
+ new (ptr.p) Table(c_attributePool, c_fragmentPool);
+ }
+ tables.release();
+ }
+
+ {
+ ArrayList<BackupFile> ops(c_backupFilePool);
+ BackupFilePtr ptr;
+ while(ops.seize(ptr)){
+ new (ptr.p) BackupFile(* this, c_pagePool);
+ }
+ ops.release();
+ }
+
+ {
+ ArrayList<BackupRecord> recs(c_backupPool);
+ BackupRecordPtr ptr;
+ while(recs.seize(ptr)){
+ new (ptr.p) BackupRecord(* this, c_pagePool, c_tablePool,
+ c_backupFilePool, c_triggerPool);
+ }
+ recs.release();
+ }
+
+ // Initialize BAT for interface to file system
+ {
+ Page32Ptr p;
+ ndbrequire(c_pagePool.seizeId(p, 0));
+ c_startOfPages = (Uint32 *)p.p;
+ c_pagePool.release(p);
+
+ NewVARIABLE* bat = allocateBat(1);
+ bat[0].WA = c_startOfPages;
+ bat[0].nrr = c_pagePool.getSize()*sizeof(Page32)/sizeof(Uint32);
+ }
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
void
Backup::execSTTOR(Signal* signal)
{
@@ -166,6 +266,65 @@ Backup::execCONTINUEB(Signal* signal)
const Uint32 Tdata2 = signal->theData[2];
switch(Tdata0) {
+ case BackupContinueB::BACKUP_FRAGMENT_INFO:
+ {
+ const Uint32 ptr_I = Tdata1;
+ Uint32 tabPtr_I = Tdata2;
+ Uint32 fragPtr_I = signal->theData[3];
+
+ BackupRecordPtr ptr;
+ c_backupPool.getPtr(ptr, ptr_I);
+ TablePtr tabPtr;
+ ptr.p->tables.getPtr(tabPtr, tabPtr_I);
+ FragmentPtr fragPtr;
+ tabPtr.p->fragments.getPtr(fragPtr, fragPtr_I);
+
+ BackupFilePtr filePtr;
+ ptr.p->files.getPtr(filePtr, ptr.p->ctlFilePtr);
+
+ const Uint32 sz = sizeof(BackupFormat::CtlFile::FragmentInfo) >> 2;
+ Uint32 * dst;
+ if (!filePtr.p->operation.dataBuffer.getWritePtr(&dst, sz))
+ {
+ sendSignalWithDelay(BACKUP_REF, GSN_CONTINUEB, signal, 100, 4);
+ return;
+ }
+
+ BackupFormat::CtlFile::FragmentInfo * fragInfo =
+ (BackupFormat::CtlFile::FragmentInfo*)dst;
+ fragInfo->SectionType = htonl(BackupFormat::FRAGMENT_INFO);
+ fragInfo->SectionLength = htonl(sz);
+ fragInfo->TableId = htonl(fragPtr.p->tableId);
+ fragInfo->FragmentNo = htonl(fragPtr_I);
+ fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF);
+ fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32);
+ fragInfo->FilePosLow = htonl(0 & 0xFFFFFFFF);
+ fragInfo->FilePosHigh = htonl(0 >> 32);
+
+ filePtr.p->operation.dataBuffer.updateWritePtr(sz);
+
+ fragPtr_I++;
+ if (fragPtr_I == tabPtr.p->fragments.getSize())
+ {
+ signal->theData[0] = tabPtr.p->tableId;
+ signal->theData[1] = 0; // unlock
+ EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
+
+ fragPtr_I = 0;
+ ptr.p->tables.next(tabPtr);
+ if ((tabPtr_I = tabPtr.i) == RNIL)
+ {
+ closeFiles(signal, ptr);
+ return;
+ }
+ }
+ signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO;
+ signal->theData[1] = ptr_I;
+ signal->theData[2] = tabPtr_I;
+ signal->theData[3] = fragPtr_I;
+ sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
+ return;
+ }
case BackupContinueB::START_FILE_THREAD:
case BackupContinueB::BUFFER_UNDERFLOW:
{
@@ -355,7 +514,7 @@ Backup::findTable(const BackupRecordPtr & ptr,
return false;
}
-static Uint32 xps(Uint32 x, Uint64 ms)
+static Uint32 xps(Uint64 x, Uint64 ms)
{
float fx = x;
float fs = ms;
@@ -369,9 +528,9 @@ static Uint32 xps(Uint32 x, Uint64 ms)
}
struct Number {
- Number(Uint32 r) { val = r;}
- Number & operator=(Uint32 r) { val = r; return * this; }
- Uint32 val;
+ Number(Uint64 r) { val = r;}
+ Number & operator=(Uint64 r) { val = r; return * this; }
+ Uint64 val;
};
NdbOut &
@@ -445,8 +604,10 @@ Backup::execBACKUP_COMPLETE_REP(Signal* signal)
startTime = NdbTick_CurrentMillisecond() - startTime;
ndbout_c("Backup %d has completed", rep->backupId);
- const Uint32 bytes = rep->noOfBytes;
- const Uint32 records = rep->noOfRecords;
+ const Uint64 bytes =
+ rep->noOfBytesLow + (((Uint64)rep->noOfBytesHigh) << 32);
+ const Uint64 records =
+ rep->noOfRecordsLow + (((Uint64)rep->noOfRecordsHigh) << 32);
Number rps = xps(records, startTime);
Number bps = xps(bytes, startTime);
@@ -959,7 +1120,7 @@ Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
}
if(errorCode != BackupRef::IAmNotMaster){
- signal->theData[0] = EventReport::BackupFailedToStart;
+ signal->theData[0] = NDB_LE_BackupFailedToStart;
signal->theData[1] = senderRef;
signal->theData[2] = errorCode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -1218,7 +1379,7 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
BackupConf::SignalLength, JBB);
}
- signal->theData[0] = EventReport::BackupStarted;
+ signal->theData[0] = NDB_LE_BackupStarted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+3);
@@ -1805,8 +1966,10 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
const Uint32 tableId = conf->tableId;
const Uint32 fragmentNo = conf->fragmentNo;
const Uint32 nodeId = refToNode(signal->senderBlockRef());
- const Uint32 noOfBytes = conf->noOfBytes;
- const Uint32 noOfRecords = conf->noOfRecords;
+ const Uint64 noOfBytes =
+ conf->noOfBytesLow + (((Uint64)conf->noOfBytesHigh) << 32);
+ const Uint64 noOfRecords =
+ conf->noOfRecordsLow + (((Uint64)conf->noOfRecordsHigh) << 32);
BackupRecordPtr ptr;
c_backupPool.getPtr(ptr, ptrI);
@@ -1818,9 +1981,13 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
TablePtr tabPtr;
ndbrequire(findTable(ptr, tabPtr, tableId));
+ tabPtr.p->noOfRecords += noOfRecords;
+
FragmentPtr fragPtr;
tabPtr.p->fragments.getPtr(fragPtr, fragmentNo);
+ fragPtr.p->noOfRecords = noOfRecords;
+
ndbrequire(fragPtr.p->scanned == 0);
ndbrequire(fragPtr.p->scanning == 1);
ndbrequire(fragPtr.p->node == nodeId);
@@ -1844,6 +2011,24 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal)
}
else
{
+ NodeBitmask nodes = ptr.p->nodes;
+ nodes.clear(getOwnNodeId());
+ if (!nodes.isclear())
+ {
+ BackupFragmentCompleteRep *rep =
+ (BackupFragmentCompleteRep*)signal->getDataPtrSend();
+ rep->backupId = ptr.p->backupId;
+ rep->backupPtr = ptr.i;
+ rep->tableId = tableId;
+ rep->fragmentNo = fragmentNo;
+ rep->noOfTableRowsLow = (Uint32)(tabPtr.p->noOfRecords & 0xFFFFFFFF);
+ rep->noOfTableRowsHigh = (Uint32)(tabPtr.p->noOfRecords >> 32);
+ rep->noOfFragmentRowsLow = (Uint32)(noOfRecords & 0xFFFFFFFF);
+ rep->noOfFragmentRowsHigh = (Uint32)(noOfRecords >> 32);
+ NodeReceiverGroup rg(BACKUP, ptr.p->nodes);
+ sendSignal(rg, GSN_BACKUP_FRAGMENT_COMPLETE_REP, signal,
+ BackupFragmentCompleteRep::SignalLength, JBB);
+ }
nextFragment(signal, ptr);
}
}
@@ -1906,6 +2091,29 @@ err:
execABORT_BACKUP_ORD(signal);
}
+void
+Backup::execBACKUP_FRAGMENT_COMPLETE_REP(Signal* signal)
+{
+ jamEntry();
+ BackupFragmentCompleteRep * rep =
+ (BackupFragmentCompleteRep*)signal->getDataPtr();
+
+ BackupRecordPtr ptr;
+ c_backupPool.getPtr(ptr, rep->backupPtr);
+
+ TablePtr tabPtr;
+ ndbrequire(findTable(ptr, tabPtr, rep->tableId));
+
+ tabPtr.p->noOfRecords =
+ rep->noOfTableRowsLow + (((Uint64)rep->noOfTableRowsHigh) << 32);
+
+ FragmentPtr fragPtr;
+ tabPtr.p->fragments.getPtr(fragPtr, rep->fragmentNo);
+
+ fragPtr.p->noOfRecords =
+ rep->noOfFragmentRowsLow + (((Uint64)rep->noOfFragmentRowsHigh) << 32);
+}
+
/*****************************************************************************
*
* Master functionallity - Drop triggers
@@ -2106,8 +2314,10 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
rep->senderData = ptr.p->clientData;
rep->startGCP = ptr.p->startGCP;
rep->stopGCP = ptr.p->stopGCP;
- rep->noOfBytes = ptr.p->noOfBytes;
- rep->noOfRecords = ptr.p->noOfRecords;
+ rep->noOfBytesLow = (Uint32)(ptr.p->noOfBytes & 0xFFFFFFFF);
+ rep->noOfRecordsLow = (Uint32)(ptr.p->noOfRecords & 0xFFFFFFFF);
+ rep->noOfBytesHigh = (Uint32)(ptr.p->noOfBytes >> 32);
+ rep->noOfRecordsHigh = (Uint32)(ptr.p->noOfRecords >> 32);
rep->noOfLogBytes = ptr.p->noOfLogBytes;
rep->noOfLogRecords = ptr.p->noOfLogRecords;
rep->nodes = ptr.p->nodes;
@@ -2115,17 +2325,19 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
BackupCompleteRep::SignalLength, JBB);
}
- signal->theData[0] = EventReport::BackupCompleted;
+ signal->theData[0] = NDB_LE_BackupCompleted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
signal->theData[3] = ptr.p->startGCP;
signal->theData[4] = ptr.p->stopGCP;
- signal->theData[5] = ptr.p->noOfBytes;
- signal->theData[6] = ptr.p->noOfRecords;
+ signal->theData[5] = (Uint32)(ptr.p->noOfBytes & 0xFFFFFFFF);
+ signal->theData[6] = (Uint32)(ptr.p->noOfRecords & 0xFFFFFFFF);
signal->theData[7] = ptr.p->noOfLogBytes;
signal->theData[8] = ptr.p->noOfLogRecords;
ptr.p->nodes.copyto(NdbNodeBitmask::Size, signal->theData+9);
- sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 9+NdbNodeBitmask::Size, JBB);
+ signal->theData[9+NdbNodeBitmask::Size] = (Uint32)(ptr.p->noOfBytes >> 32);
+ signal->theData[10+NdbNodeBitmask::Size] = (Uint32)(ptr.p->noOfRecords >> 32);
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 11+NdbNodeBitmask::Size, JBB);
}
else
{
@@ -2160,7 +2372,7 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
BackupAbortRep::SignalLength, JBB);
}
- signal->theData[0] = EventReport::BackupAborted;
+ signal->theData[0] = NDB_LE_BackupAborted;
signal->theData[1] = ptr.p->clientRef;
signal->theData[2] = ptr.p->backupId;
signal->theData[3] = ptr.p->errorCode;
@@ -2324,7 +2536,6 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
};
const Uint32 maxInsert[] = {
2048, // Temporarily to solve TR515
- //25, // 100 bytes
4096, // 4k
16*3000, // Max 16 tuples
};
@@ -2889,8 +3100,7 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
/**
* Initialize table object
*/
- tabPtr.p->frag_mask = RNIL;
-
+ tabPtr.p->noOfRecords = 0;
tabPtr.p->schemaVersion = tmpTab.TableVersion;
tabPtr.p->noOfAttributes = tmpTab.NoOfAttributes;
tabPtr.p->noOfNull = 0;
@@ -2983,7 +3193,6 @@ Backup::execDI_FCOUNTCONF(Signal* signal)
ndbrequire(findTable(ptr, tabPtr, tableId));
ndbrequire(tabPtr.p->fragments.seize(fragCount) != false);
- tabPtr.p->frag_mask = calculate_frag_mask(fragCount);
for(Uint32 i = 0; i<fragCount; i++) {
jam();
FragmentPtr fragPtr;
@@ -3599,8 +3808,10 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
conf->backupPtr = ptr.i;
conf->tableId = filePtr.p->tableId;
conf->fragmentNo = filePtr.p->fragmentNo;
- conf->noOfRecords = op.noOfRecords;
- conf->noOfBytes = op.noOfBytes;
+ conf->noOfRecordsLow = (Uint32)(op.noOfRecords & 0xFFFFFFFF);
+ conf->noOfRecordsHigh = (Uint32)(op.noOfRecords >> 32);
+ conf->noOfBytesLow = (Uint32)(op.noOfBytes & 0xFFFFFFFF);
+ conf->noOfBytesHigh = (Uint32)(op.noOfBytes >> 32);
sendSignal(ptr.p->masterRef, GSN_BACKUP_FRAGMENT_CONF, signal,
BackupFragmentConf::SignalLength, JBB);
@@ -3801,15 +4012,6 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr)
* Slave functionallity: Perform logging
*
****************************************************************************/
-Uint32
-Backup::calculate_frag_mask(Uint32 count)
-{
- Uint32 mask = 1;
- while (mask < count) mask <<= 1;
- mask -= 1;
- return mask;
-}
-
void
Backup::execBACKUP_TRIG_REQ(Signal* signal)
{
@@ -3826,14 +4028,6 @@ Backup::execBACKUP_TRIG_REQ(Signal* signal)
jamEntry();
c_triggerPool.getPtr(trigPtr, trigger_id);
c_tablePool.getPtr(tabPtr, trigPtr.p->tab_ptr_i);
- frag_id = frag_id & tabPtr.p->frag_mask;
- /*
- At the moment the fragment identity known by TUP is the
- actual fragment id but with possibly an extra bit set.
- This is due to that ACC splits the fragment. Thus fragment id 5 can
- here be either 5 or 13. Thus masking with 2 ** n - 1 where number of
- fragments <= 2 ** n will always provide a correct fragment id.
- */
tabPtr.p->fragments.getPtr(fragPtr, frag_id);
if (fragPtr.p->node != getOwnNodeId()) {
jam();
@@ -4044,20 +4238,18 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal)
gcp->StartGCP = htonl(startGCP);
gcp->StopGCP = htonl(stopGCP - 1);
filePtr.p->operation.dataBuffer.updateWritePtr(gcpSz);
- }
- {
- TablePtr tabPtr;
- for(ptr.p->tables.first(tabPtr); tabPtr.i != RNIL;
- ptr.p->tables.next(tabPtr))
{
- signal->theData[0] = tabPtr.p->tableId;
- signal->theData[1] = 0; // unlock
- EXECUTE_DIRECT(DBDICT, GSN_BACKUP_FRAGMENT_REQ, signal, 2);
+ TablePtr tabPtr;
+ ptr.p->tables.first(tabPtr);
+
+ signal->theData[0] = BackupContinueB::BACKUP_FRAGMENT_INFO;
+ signal->theData[1] = ptr.i;
+ signal->theData[2] = tabPtr.i;
+ signal->theData[3] = 0;
+ sendSignal(BACKUP_REF, GSN_CONTINUEB, signal, 4, JBB);
}
}
-
- closeFiles(signal, ptr);
}
void
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index f3d180b9467..e37923da749 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -46,6 +46,7 @@ public:
protected:
void execSTTOR(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
void execREAD_NODESCONF(Signal* signal);
void execNODE_FAILREP(Signal* signal);
@@ -67,6 +68,7 @@ protected:
void execBACKUP_DATA(Signal* signal);
void execSTART_BACKUP_REQ(Signal* signal);
void execBACKUP_FRAGMENT_REQ(Signal* signal);
+ void execBACKUP_FRAGMENT_COMPLETE_REP(Signal* signal);
void execSTOP_BACKUP_REQ(Signal* signal);
void execBACKUP_STATUS_REQ(Signal* signal);
void execABORT_BACKUP_ORD(Signal* signal);
@@ -182,10 +184,12 @@ public:
typedef Ptr<Attribute> AttributePtr;
struct Fragment {
+ Uint64 noOfRecords;
Uint32 tableId;
- Uint32 node;
- Uint16 scanned; // 0 = not scanned x = scanned by node x
- Uint16 scanning; // 0 = not scanning x = scanning on node x
+ Uint8 node;
+ Uint8 scanned; // 0 = not scanned x = scanned by node x
+ Uint8 scanning; // 0 = not scanning x = scanning on node x
+ Uint8 unused1;
Uint32 nextPool;
};
typedef Ptr<Fragment> FragmentPtr;
@@ -193,9 +197,10 @@ public:
struct Table {
Table(ArrayPool<Attribute> &, ArrayPool<Fragment> &);
+ Uint64 noOfRecords;
+
Uint32 tableId;
Uint32 schemaVersion;
- Uint32 frag_mask;
Uint32 tableType;
Uint32 noOfNull;
Uint32 noOfAttributes;
@@ -269,8 +274,8 @@ public:
Uint32 tablePtr; // Ptr.i to current table
FsBuffer dataBuffer;
- Uint32 noOfRecords;
- Uint32 noOfBytes;
+ Uint64 noOfRecords;
+ Uint64 noOfBytes;
Uint32 maxRecordSize;
private:
@@ -527,8 +532,6 @@ public:
ArrayPool<Node> c_nodePool;
ArrayPool<TriggerRecord> c_triggerPool;
- Uint32 calculate_frag_mask(Uint32);
-
void checkFile(Signal*, BackupFilePtr);
void checkScan(Signal*, BackupFilePtr);
void fragmentCompleted(Signal*, BackupFilePtr);
diff --git a/ndb/src/kernel/blocks/backup/BackupFormat.hpp b/ndb/src/kernel/blocks/backup/BackupFormat.hpp
index 65dd2ad9053..b8ffff3a294 100644
--- a/ndb/src/kernel/blocks/backup/BackupFormat.hpp
+++ b/ndb/src/kernel/blocks/backup/BackupFormat.hpp
@@ -32,7 +32,8 @@ struct BackupFormat {
FRAGMENT_FOOTER = 3,
TABLE_LIST = 4,
TABLE_DESCRIPTION = 5,
- GCP_ENTRY = 6
+ GCP_ENTRY = 6,
+ FRAGMENT_INFO = 7
};
struct FileHeader {
@@ -126,6 +127,20 @@ struct BackupFormat {
Uint32 StartGCP;
Uint32 StopGCP;
};
+
+ /**
+ * Fragment Info
+ */
+ struct FragmentInfo {
+ Uint32 SectionType;
+ Uint32 SectionLength;
+ Uint32 TableId;
+ Uint32 FragmentNo;
+ Uint32 NoOfRecordsLow;
+ Uint32 NoOfRecordsHigh;
+ Uint32 FilePosLow;
+ Uint32 FilePosHigh;
+ };
};
/**
diff --git a/ndb/src/kernel/blocks/backup/BackupInit.cpp b/ndb/src/kernel/blocks/backup/BackupInit.cpp
index dfda31e9b48..96c11468939 100644
--- a/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -34,90 +34,10 @@ Backup::Backup(const Configuration & conf) :
{
BLOCK_CONSTRUCTOR(Backup);
- c_nodePool.setSize(MAX_NDB_NODES);
c_masterNodeId = getOwnNodeId();
- const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- Uint32 noBackups = 0, noTables = 0, noAttribs = 0, noFrags = 0;
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &m_diskless));
- ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_BACKUPS, &noBackups);
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &noTables));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE, &noAttribs));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_FRAG_CONNECT, &noFrags));
-
- noAttribs++; //RT 527 bug fix
-
- c_backupPool.setSize(noBackups);
- c_backupFilePool.setSize(3 * noBackups);
- c_tablePool.setSize(noBackups * noTables);
- c_attributePool.setSize(noBackups * noAttribs);
- c_triggerPool.setSize(noBackups * 3 * noTables);
-
- c_fragmentPool.setSize(noBackups * noFrags);
-
- Uint32 szMem = 0;
- ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MEM, &szMem);
- Uint32 noPages = (szMem + sizeof(Page32) - 1) / sizeof(Page32);
- // We need to allocate an additional of 2 pages. 1 page because of a bug in
- // ArrayPool and another one for DICTTAINFO.
- c_pagePool.setSize(noPages + NO_OF_PAGES_META_FILE + 2);
-
- Uint32 szDataBuf = (2 * 1024 * 1024);
- Uint32 szLogBuf = (2 * 1024 * 1024);
- Uint32 szWrite = 32768, maxWriteSize = (256 * 1024);
- ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_DATA_BUFFER_MEM, &szDataBuf);
- ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_LOG_BUFFER_MEM, &szLogBuf);
- ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_WRITE_SIZE, &szWrite);
- ndb_mgm_get_int_parameter(p, CFG_DB_BACKUP_MAX_WRITE_SIZE, &maxWriteSize);
-
- c_defaults.m_logBufferSize = szLogBuf;
- c_defaults.m_dataBufferSize = szDataBuf;
- c_defaults.m_minWriteSize = szWrite;
- c_defaults.m_maxWriteSize = maxWriteSize;
-
- { // Init all tables
- ArrayList<Table> tables(c_tablePool);
- TablePtr ptr;
- while(tables.seize(ptr)){
- new (ptr.p) Table(c_attributePool, c_fragmentPool);
- }
- tables.release();
- }
-
- {
- ArrayList<BackupFile> ops(c_backupFilePool);
- BackupFilePtr ptr;
- while(ops.seize(ptr)){
- new (ptr.p) BackupFile(* this, c_pagePool);
- }
- ops.release();
- }
-
- {
- ArrayList<BackupRecord> recs(c_backupPool);
- BackupRecordPtr ptr;
- while(recs.seize(ptr)){
- new (ptr.p) BackupRecord(* this, c_pagePool, c_tablePool,
- c_backupFilePool, c_triggerPool);
- }
- recs.release();
- }
-
- // Initialize BAT for interface to file system
- {
- Page32Ptr p;
- ndbrequire(c_pagePool.seizeId(p, 0));
- c_startOfPages = (Uint32 *)p.p;
- c_pagePool.release(p);
-
- NewVARIABLE* bat = allocateBat(1);
- bat[0].WA = c_startOfPages;
- bat[0].nrr = c_pagePool.getSize()*sizeof(Page32)/sizeof(Uint32);
- }
-
// Add received signals
+ addRecSignal(GSN_READ_CONFIG_REQ, &Backup::execREAD_CONFIG_REQ);
addRecSignal(GSN_STTOR, &Backup::execSTTOR);
addRecSignal(GSN_DUMP_STATE_ORD, &Backup::execDUMP_STATE_ORD);
addRecSignal(GSN_READ_NODESCONF, &Backup::execREAD_NODESCONF);
@@ -177,6 +97,9 @@ Backup::Backup(const Configuration & conf) :
addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Backup::execBACKUP_FRAGMENT_REQ);
addRecSignal(GSN_BACKUP_FRAGMENT_REF, &Backup::execBACKUP_FRAGMENT_REF);
addRecSignal(GSN_BACKUP_FRAGMENT_CONF, &Backup::execBACKUP_FRAGMENT_CONF);
+
+ addRecSignal(GSN_BACKUP_FRAGMENT_COMPLETE_REP,
+ &Backup::execBACKUP_FRAGMENT_COMPLETE_REP);
addRecSignal(GSN_STOP_BACKUP_REQ, &Backup::execSTOP_BACKUP_REQ);
addRecSignal(GSN_STOP_BACKUP_REF, &Backup::execSTOP_BACKUP_REF);
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index f9290a75afb..d2f9150ade0 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -72,6 +72,7 @@ Cmvmi::Cmvmi(const Configuration & conf) :
addRecSignal(GSN_SET_LOGLEVELORD, &Cmvmi::execSET_LOGLEVELORD);
addRecSignal(GSN_EVENT_REP, &Cmvmi::execEVENT_REP);
addRecSignal(GSN_STTOR, &Cmvmi::execSTTOR);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Cmvmi::execREAD_CONFIG_REQ);
addRecSignal(GSN_CLOSE_COMREQ, &Cmvmi::execCLOSE_COMREQ);
addRecSignal(GSN_ENABLE_COMORD, &Cmvmi::execENABLE_COMORD);
addRecSignal(GSN_OPEN_COMREQ, &Cmvmi::execOPEN_COMREQ);
@@ -191,7 +192,13 @@ void Cmvmi::execEVENT_REP(Signal* signal)
// to the graphical management interface.
//-----------------------------------------------------------------------
EventReport * const eventReport = (EventReport *)&signal->theData[0];
- EventReport::EventType eventType = eventReport->getEventType();
+ Ndb_logevent_type eventType = eventReport->getEventType();
+ Uint32 nodeId= eventReport->getNodeId();
+ if (nodeId == 0)
+ {
+ nodeId= refToNode(signal->getSendersBlockRef());
+ eventReport->setNodeId(nodeId);
+ }
jamEntry();
@@ -201,7 +208,8 @@ void Cmvmi::execEVENT_REP(Signal* signal)
Uint32 threshold;
LogLevel::EventCategory eventCategory;
Logger::LoggerLevel severity;
- if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity))
+ EventLoggerBase::EventTextFunction textF;
+ if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity,textF))
return;
SubscriberPtr ptr;
@@ -304,6 +312,27 @@ void Cmvmi::sendSTTORRY(Signal* signal)
}//Cmvmi::sendSTTORRY
+void
+Cmvmi::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
void Cmvmi::execSTTOR(Signal* signal)
{
Uint32 theStartPhase = signal->theData[1];
@@ -366,7 +395,7 @@ void Cmvmi::execCLOSE_COMREQ(Signal* signal)
//-----------------------------------------------------
// Report that the connection to the node is closed
//-----------------------------------------------------
- signal->theData[0] = EventReport::CommunicationClosed;
+ signal->theData[0] = NDB_LE_CommunicationClosed;
signal->theData[1] = i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -405,7 +434,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
//-----------------------------------------------------
// Report that the connection to the node is opened
//-----------------------------------------------------
- signal->theData[0] = EventReport::CommunicationOpened;
+ signal->theData[0] = NDB_LE_CommunicationOpened;
signal->theData[1] = tStartingNode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
//-----------------------------------------------------
@@ -424,7 +453,7 @@ void Cmvmi::execOPEN_COMREQ(Signal* signal)
globalTransporterRegistry.do_connect(i);
globalTransporterRegistry.setIOState(i, HaltIO);
- signal->theData[0] = EventReport::CommunicationOpened;
+ signal->theData[0] = NDB_LE_CommunicationOpened;
signal->theData[1] = i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}
@@ -449,7 +478,7 @@ void Cmvmi::execENABLE_COMORD(Signal* signal)
//-----------------------------------------------------
// Report that the version of the node
//-----------------------------------------------------
- signal->theData[0] = EventReport::ConnectedApiVersion;
+ signal->theData[0] = NDB_LE_ConnectedApiVersion;
signal->theData[1] = tStartingNode;
signal->theData[2] = getNodeInfo(tStartingNode).m_version;
@@ -491,7 +520,7 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal)
cancelSubscription(hostId);
- signal->theData[0] = EventReport::Disconnected;
+ signal->theData[0] = NDB_LE_Disconnected;
signal->theData[1] = hostId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}
@@ -541,7 +570,7 @@ void Cmvmi::execCONNECT_REP(Signal *signal){
//------------------------------------------
// Also report this event to the Event handler
//------------------------------------------
- signal->theData[0] = EventReport::Connected;
+ signal->theData[0] = NDB_LE_Connected;
signal->theData[1] = hostId;
signal->header.theLength = 2;
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
index 1c91f564749..f89c8f15e86 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp
@@ -48,6 +48,7 @@ private:
void execNDB_TAMPER(Signal* signal);
void execSET_LOGLEVELORD(Signal* signal);
void execEVENT_REP(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void execCLOSE_COMREQ(Signal* signal);
void execENABLE_COMORD(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index ea866aafff9..7f51a281f37 100644
--- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -22,6 +22,9 @@
#include <pc.hpp>
#include <SimulatedBlock.hpp>
+// primary key is stored in TUP
+#include <Dbtup.hpp>
+
#ifdef DBACC_C
// Debug Macros
#define dbgWord32(ptr, ind, val)
@@ -98,7 +101,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZPOS_PREV_PAGE 11
#define ZNORMAL_PAGE_TYPE 0
#define ZOVERFLOW_PAGE_TYPE 1
-#define ZLONG_PAGE_TYPE 2
#define ZDEFAULT_LIST 3
#define ZWORDS_IN_PAGE 2048
/* --------------------------------------------------------------------------------- */
@@ -132,16 +134,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZPAGEZERO_NODETYPE 33
#define ZPAGEZERO_SLACK_CHECK 34
/* --------------------------------------------------------------------------------- */
-/* CONSTANTS FOR THE LONG KEY PAGES */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-// Maximum number of elements in long key page = (ZWORDS_IN_PAGE - ZHEAD_SIZE) /
-// (MinKeySize + IndexSize) = (2048 - 32) / (8 + 1) = 224. MinKeySize is actually 9
-// because 8 is the largest normal key size.
-#define ZMAX_NO_OF_LONGKEYS_IN_PAGE 225
-#define ZMAX_LONG_KEY_ARRAY_INDEX 3
-#define ZACTIVE_LONG_KEY_LEN 1
-/* --------------------------------------------------------------------------------- */
/* CONSTANTS IN ALPHABETICAL ORDER */
/* --------------------------------------------------------------------------------- */
#define ZADDFRAG 0
@@ -392,49 +384,6 @@ enum State {
// Records
-
-//----------------------------------------------------------------------------------
-// LONGKEY PAGE RECORD
-//
-// A long key page consist of a header part, a key data part and an index part. The
-// page starts with a header of size HEAD_SIZE. As you can see below, not every word
-// in the header is used. After the header comes the data part, where the actual
-// keys are stored. A key is always inserted after the existing keys in the data
-// part. If we have a fragmented data part and a new key doesn't fit after the
-// existing keys we reorganize the keys. The index part starts at the end of the
-// page and grows towards the end of the data part. This means that the limit
-// between the data part and the index part is floating. Each inserted key have a
-// word in the index part that describes size and position of the key in the data
-// part. The free indexes in the index part are single linked.
-//----------------------------------------------------------------------------------
- union LongKeyPage {
- struct {
- Uint32 pageId; // ZPOS_PAGE_ID 0
- Uint32 b;
- // The number of keys in page.
- Uint32 noOfElements; // ZPOS_NO_ELEM_IN_PAGE 2
- Uint32 d;
- Uint32 e;
- // The free area in the data part of page.
- Uint32 freeArea; // ZPOS_FREE_AREA_IN_PAGE 5
- // The index position, which defines the limit between the data and the index part.
- Uint32 highestIndex; // ZPOS_LAST_INDEX 6
- // The position where to insert the actual key in the data part.
- Uint32 insertPos; // ZPOS_INSERT_INDEX 7
- // Position in a page array where the pages are stored in a double linked list.
- // Based on the free area in the page. Values 0 to 3.
- Uint32 pageArrayPos; // ZPOS_ARRAY_POS 8
- // Next free position in the index part.
- Uint32 nextFreeIndex; // ZPOS_NEXT_FREE_INDEX 9
- // Next page in the double linked list.
- Uint32 nextPage; // ZPOS_NEXT_PAGE 10
- // Previous page in the double linked list.
- Uint32 prevPage; // ZPOS_PREV_PAGE 11
- } header;
- // This is kept to keep the logic and to make changes to a minimum.
- Uint32 word32[2048];
- };
-
/* --------------------------------------------------------------------------------- */
/* UNDO HEADER RECORD */
/* --------------------------------------------------------------------------------- */
@@ -444,9 +393,7 @@ enum State {
ZPAGE_INFO = 0,
ZOVER_PAGE_INFO = 1,
ZOP_INFO = 2,
- ZUNDO_INSERT_LONG_KEY = 3,
- ZUNDO_DELETE_LONG_KEY = 4,
- ZNO_UNDORECORD_TYPES = 5
+ ZNO_UNDORECORD_TYPES = 3
};
UintR tableId;
UintR rootFragId;
@@ -660,10 +607,10 @@ struct Fragmentrec {
//-----------------------------------------------------------------------------
// elementLength: Length of element in bucket and overflow pages
-// keyLength: Length of key (== 0 if long key or variable key length)
+// keyLength: Length of key
//-----------------------------------------------------------------------------
Uint8 elementLength;
- Uint8 keyLength;
+ Uint16 keyLength;
//-----------------------------------------------------------------------------
// This flag is used to avoid sending a big number of expand or shrink signals
@@ -689,6 +636,11 @@ struct Fragmentrec {
//-----------------------------------------------------------------------------
Uint8 nodetype;
Uint8 stopQueOp;
+
+//-----------------------------------------------------------------------------
+// flag to avoid accessing table record if no char attributes
+//-----------------------------------------------------------------------------
+ Uint8 hasCharAttr;
};
typedef Ptr<Fragmentrec> FragmentrecPtr;
@@ -771,6 +723,7 @@ struct Operationrec {
State transactionstate;
Uint16 elementContainer;
Uint16 tupkeylen;
+ Uint32 xfrmtupkeylen;
Uint32 userblockref;
Uint32 scanBits;
Uint8 elementIsDisappeared;
@@ -783,7 +736,7 @@ struct Operationrec {
Uint8 dirtyRead;
Uint8 commitDeleteCheckFlag;
Uint8 isAccLockReq;
- Uint32 nextOpList;
+ Uint8 isUndoLogReq;
}; /* p2c: size = 168 bytes */
typedef Ptr<Operationrec> OperationrecPtr;
@@ -914,6 +867,9 @@ public:
Dbacc(const class Configuration &);
virtual ~Dbacc();
+ // pointer to TUP instance in this thread
+ Dbtup* c_tup;
+
private:
BLOCK_DEFINES(Dbacc);
@@ -972,10 +928,8 @@ private:
void initFragGeneral(FragmentrecPtr);
void verifyFragCorrect(FragmentrecPtr regFragPtr);
void sendFSREMOVEREQ(Signal* signal, Uint32 tableId);
- void sendDROP_TABFILECONF(Signal* signal, TabrecPtr tabPtr);
void releaseFragResources(Signal* signal, Uint32 fragIndex);
void releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr);
- void sendREL_TABMEMCONF(Signal* signal, TabrecPtr tabPtr);
void releaseRootFragResources(Signal* signal, Uint32 tableId);
void releaseDirResources(Signal* signal,
Uint32 fragIndex,
@@ -1051,7 +1005,6 @@ private:
void releaseScanRec(Signal* signal);
bool searchScanContainer(Signal* signal);
void sendNextScanConf(Signal* signal);
- void sendScaninfo(Signal* signal);
void setlock(Signal* signal);
void takeOutActiveScanOp(Signal* signal);
void takeOutScanLockQueue(Uint32 scanRecIndex);
@@ -1063,15 +1016,8 @@ private:
void increaselistcont(Signal* signal);
void seizeLeftlist(Signal* signal);
void seizeRightlist(Signal* signal);
- void allocLongOverflowPage(Signal* signal);
- void allocSpecificLongOverflowPage(Signal* signal);
- void getLongKeyPage(Signal* signal);
- void initLongOverpage(Signal* signal);
- void storeLongKeys(Signal* signal);
- void storeLongKeysAtPos(Signal* signal);
- void reorgLongPage(Signal* signal);
+ Uint32 readTablePk(Uint32 localkey1);
void getElement(Signal* signal);
- void searchLongKey(Signal* signal, bool verify);
void getdirindex(Signal* signal);
void commitdelete(Signal* signal, bool systemRestart);
void deleteElement(Signal* signal);
@@ -1079,15 +1025,6 @@ private:
void releaseLeftlist(Signal* signal);
void releaseRightlist(Signal* signal);
void checkoverfreelist(Signal* signal);
- void deleteLongKey(Signal* signal);
- void removeFromPageArrayList(Signal* signal);
- void insertPageArrayList(Signal* signal);
- void checkPageArrayList(Signal* signal, const char *);
- void checkPageB4Insert(Uint32, const char *);
- void checkPageB4Remove(Uint32, const char *);
- void checkIndexInLongKeyPage(Uint32, const char *);
- void printoutInfoAndShutdown(LongKeyPage *);
- void releaseLongPage(Signal* signal);
void abortOperation(Signal* signal);
void accAbortReqLab(Signal* signal, bool sendConf);
void commitOperation(Signal* signal);
@@ -1105,7 +1042,6 @@ private:
void initLcpConnRec(Signal* signal);
void initOverpage(Signal* signal);
void initPage(Signal* signal);
- void initPageZero(Signal* signal);
void initRootfragrec(Signal* signal);
void putOpInFragWaitQue(Signal* signal);
void putOverflowRecInFrag(Signal* signal);
@@ -1135,7 +1071,7 @@ private:
void seizeRootfragrec(Signal* signal);
void seizeScanRec(Signal* signal);
void seizeSrVerRec(Signal* signal);
- void sendSystemerror(Signal* signal);
+ void sendSystemerror(Signal* signal, int line);
void takeRecOutOfFreeOverdir(Signal* signal);
void takeRecOutOfFreeOverpage(Signal* signal);
void sendScanHbRep(Signal* signal, Uint32);
@@ -1159,8 +1095,6 @@ private:
void refaccConnectLab(Signal* signal);
void srReadOverPagesLab(Signal* signal);
void releaseScanLab(Signal* signal);
- void exeoperationLab(Signal* signal);
- void saveKeyDataLab(Signal* signal);
void lcpOpenUndofileConfLab(Signal* signal);
void srFsOpenConfLab(Signal* signal);
void checkSyncUndoPagesLab(Signal* signal);
@@ -1172,13 +1106,12 @@ private:
void srReadPagesLab(Signal* signal);
void srDoUndoLab(Signal* signal);
void ndbrestart1Lab(Signal* signal);
- void initialiseRecordsLab(Signal* signal, Uint32 returnRef, Uint32 retData);
+ void initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data);
void srReadPagesAllocLab(Signal* signal);
void checkNextBucketLab(Signal* signal);
void endsavepageLab(Signal* signal);
void saveZeroPageLab(Signal* signal);
void srAllocPage0011Lab(Signal* signal);
- void allocscanrecLab(Signal* signal);
void sendLcpFragidconfLab(Signal* signal);
void savepagesLab(Signal* signal);
void saveOverPagesLab(Signal* signal);
@@ -1192,6 +1125,8 @@ private:
void lcp_write_op_to_undolog(Signal* signal);
void reenable_expand_after_redo_log_exection_complete(Signal*);
+ // charsets
+ void xfrmKeyData(Signal* signal);
// Initialisation
void initData();
@@ -1281,8 +1216,6 @@ private:
/* --------------------------------------------------------------------------------- */
Page8 *page8;
/* 8 KB PAGE */
- Page8Ptr aslpPageptr;
- Page8Ptr alpPageptr;
Page8Ptr ancPageptr;
Page8Ptr colPageptr;
Page8Ptr ccoPageptr;
@@ -1293,29 +1226,17 @@ private:
Page8Ptr gdiPageptr;
Page8Ptr gePageptr;
Page8Ptr gflPageptr;
- Page8Ptr glkPageptr;
Page8Ptr idrPageptr;
Page8Ptr ilcPageptr;
- Page8Ptr iloPageptr;
Page8Ptr inpPageptr;
Page8Ptr iopPageptr;
- Page8Ptr ipzPageptr;
Page8Ptr lastPageptr;
Page8Ptr lastPrevpageptr;
Page8Ptr lcnPageptr;
Page8Ptr lcnCopyPageptr;
Page8Ptr lupPageptr;
- Page8Ptr dlkPageptr;
- Page8Ptr ipaPagePtr;
Page8Ptr priPageptr;
Page8Ptr pwiPageptr;
- Page8Ptr rfpPageptr;
- Page8Ptr relpPageptr;
- Page8Ptr rlopPageptr;
- Page8Ptr slkPageptr;
- Page8Ptr slkCopyPageptr;
- Page8Ptr slkapPageptr;
- Page8Ptr slkapCopyPageptr;
Page8Ptr ciPageidptr;
Page8Ptr gsePageidptr;
Page8Ptr isoPageptr;
@@ -1329,7 +1250,6 @@ private:
Page8Ptr ropPageptr;
Page8Ptr rpPageptr;
Page8Ptr slPageptr;
- Page8Ptr slpPageptr;
Page8Ptr spPageptr;
Uint32 cfirstfreepage;
Uint32 cfreepage;
@@ -1347,7 +1267,6 @@ private:
/* --------------------------------------------------------------------------------- */
Rootfragmentrec *rootfragmentrec;
RootfragmentrecPtr rootfragrecptr;
- RootfragmentrecPtr tmprootfrgptr;
Uint32 crootfragmentsize;
Uint32 cfirstfreerootfrag;
/* --------------------------------------------------------------------------------- */
@@ -1380,7 +1299,6 @@ private:
Uint32 tpriElementptr;
Uint32 tgseElementptr;
Uint32 tgseContainerptr;
- Uint32 tiloIndex;
Uint32 trlHead;
Uint32 trlRelCon;
Uint32 trlNextused;
@@ -1389,20 +1307,12 @@ private:
Uint32 tlupElemIndex;
Uint32 tlupIndex;
Uint32 tlupForward;
- Uint32 tslkPageIndex;
- Uint32 tslkKeyLen;
- Uint32 tslkapKeyLen;
- Uint32 tslkapPageIndex;
- Uint32 tipaArrayPos;
- Uint32 trfpArrayPos;
- Uint32 tdlkLogicalPageIndex;
Uint32 tancNext;
Uint32 tancBufType;
Uint32 tancContainerptr;
Uint32 tancPageindex;
Uint32 tancPageid;
Uint32 tidrResult;
- Uint32 tidrKeyLen;
Uint32 tidrElemhead;
Uint32 tidrForward;
Uint32 tidrPageindex;
@@ -1420,15 +1330,11 @@ private:
Uint32 tdelForward;
Uint32 tiopPageId;
Uint32 tipPageId;
- Uint32 ttupKeyLength;
Uint32 tgeLocked;
Uint32 tgeResult;
Uint32 tgeContainerptr;
Uint32 tgeElementptr;
Uint32 tgeForward;
- Uint32 tslcResult;
- Uint32 tslcPagedir;
- Uint32 tslcPageIndex;
Uint32 tundoElemIndex;
Uint32 texpReceivedBucket;
Uint32 texpDirInd;
@@ -1453,7 +1359,6 @@ private:
Uint32 tscanFlag;
Uint32 theadundoindex;
Uint32 tgflBufType;
- Uint32 thashvalue;
Uint32 tgseIsforward;
Uint32 tsscIsforward;
Uint32 trscIsforward;
@@ -1462,21 +1367,10 @@ private:
Uint32 tisoIsforward;
Uint32 tgseIsLocked;
Uint32 tsscIsLocked;
- Uint32 tkey1;
- Uint32 tkey2;
- Uint32 tkey3;
- Uint32 tkey4;
Uint32 tkeylen;
- Uint32 tkSize;
- Uint32 tlhfragbits;
- Uint32 tlhdirbits;
- Uint32 tlocalkeylen;
- Uint32 tmaxloadfactor;
- Uint32 tminloadfactor;
Uint32 tmp;
Uint32 tmpP;
Uint32 tmpP2;
- Uint32 taslpDirIndex;
Uint32 tmp1;
Uint32 tmp2;
Uint32 tgflPageindex;
@@ -1490,9 +1384,6 @@ private:
Uint32 trsbPageindex;
Uint32 tnciPageindex;
Uint32 tlastPrevconptr;
- Uint32 treqinfo;
- Uint32 transactionid1;
- Uint32 transactionid2;
Uint32 tresult;
Uint32 tslUpdateHeader;
Uint32 tuserptr;
@@ -1505,15 +1396,12 @@ private:
Uint32 tgdiPageindex;
Uint32 tiopIndex;
Uint32 tnciTmp;
- Uint32 tlenKeyinfo;
Uint32 tullIndex;
Uint32 turlIndex;
Uint32 tlfrTmp1;
Uint32 tlfrTmp2;
- Uint32 tudqeIndex;
Uint32 tscanTrid1;
Uint32 tscanTrid2;
- Uint32 taccscanTmp;
Uint16 clastUndoPageIdWritten;
Uint32 cactiveCheckpId;
@@ -1557,10 +1445,13 @@ private:
Uint32 cexcPrevpageindex;
Uint32 cexcPrevforward;
Uint32 clocalkey[32];
- Uint32 ckeys[2048];
+ union {
+ Uint32 ckeys[2048 * MAX_XFRM_MULTIPLY];
+ Uint64 ckeys_align;
+ };
Uint32 c_errorInsert3000_TableId;
- Uint32 cSrUndoRecords[5];
+ Uint32 cSrUndoRecords[UndoHeader::ZNO_UNDORECORD_TYPES];
};
#endif
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index c98c072cc89..59a622b60e6 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -59,10 +59,24 @@ void Dbacc::initData()
void Dbacc::initRecords()
{
// Records with dynamic sizes
+ page8 = (Page8*)allocRecord("Page8",
+ sizeof(Page8),
+ cpagesize,
+ false);
+
+ operationrec = (Operationrec*)allocRecord("Operationrec",
+ sizeof(Operationrec),
+ coprecsize);
+
dirRange = (DirRange*)allocRecord("DirRange",
sizeof(DirRange),
cdirrangesize);
+ undopage = (Undopage*)allocRecord("Undopage",
+ sizeof(Undopage),
+ cundopagesize,
+ false);
+
directoryarray = (Directoryarray*)allocRecord("Directoryarray",
sizeof(Directoryarray),
cdirarraysize);
@@ -83,19 +97,10 @@ void Dbacc::initRecords()
sizeof(LcpConnectrec),
clcpConnectsize);
- operationrec = (Operationrec*)allocRecord("Operationrec",
- sizeof(Operationrec),
- coprecsize);
-
overflowRecord = (OverflowRecord*)allocRecord("OverflowRecord",
sizeof(OverflowRecord),
coverflowrecsize);
- page8 = (Page8*)allocRecord("Page8",
- sizeof(Page8),
- cpagesize,
- false);
-
rootfragmentrec = (Rootfragmentrec*)allocRecord("Rootfragmentrec",
sizeof(Rootfragmentrec),
crootfragmentsize);
@@ -112,11 +117,6 @@ void Dbacc::initRecords()
sizeof(Tabrec),
ctablesize);
- undopage = (Undopage*)allocRecord("Undopage",
- sizeof(Undopage),
- cundopagesize,
- false);
-
// Initialize BAT for interface to file system
NewVARIABLE* bat = allocateBat(3);
@@ -133,27 +133,11 @@ void Dbacc::initRecords()
}//Dbacc::initRecords()
Dbacc::Dbacc(const class Configuration & conf):
- SimulatedBlock(DBACC, conf)
+ SimulatedBlock(DBACC, conf),
+ c_tup(0)
{
- Uint32 log_page_size= 0;
BLOCK_CONSTRUCTOR(Dbacc);
- const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndb_mgm_get_int_parameter(p, CFG_DB_UNDO_INDEX_BUFFER,
- &log_page_size);
-
- /**
- * Always set page size in half MBytes
- */
- cundopagesize= (log_page_size / sizeof(Undopage));
- Uint32 mega_byte_part= cundopagesize & 15;
- if (mega_byte_part != 0) {
- jam();
- cundopagesize+= (16 - mega_byte_part);
- }
-
// Transit signals
addRecSignal(GSN_DUMP_STATE_ORD, &Dbacc::execDUMP_STATE_ORD);
addRecSignal(GSN_DEBUG_SIG, &Dbacc::execDEBUG_SIG);
@@ -197,6 +181,80 @@ Dbacc::Dbacc(const class Configuration & conf):
addRecSignal(GSN_SET_VAR_REQ, &Dbacc::execSET_VAR_REQ);
initData();
+
+#ifdef VM_TRACE
+ {
+ void* tmp[] = { &expDirRangePtr,
+ &gnsDirRangePtr,
+ &newDirRangePtr,
+ &rdDirRangePtr,
+ &nciOverflowrangeptr,
+ &expDirptr,
+ &rdDirptr,
+ &sdDirptr,
+ &nciOverflowDirptr,
+ &fragrecptr,
+ &fsConnectptr,
+ &fsOpptr,
+ &lcpConnectptr,
+ &operationRecPtr,
+ &idrOperationRecPtr,
+ &copyInOperPtr,
+ &copyOperPtr,
+ &mlpqOperPtr,
+ &queOperPtr,
+ &readWriteOpPtr,
+ &iopOverflowRecPtr,
+ &tfoOverflowRecPtr,
+ &porOverflowRecPtr,
+ &priOverflowRecPtr,
+ &rorOverflowRecPtr,
+ &sorOverflowRecPtr,
+ &troOverflowRecPtr,
+ &ancPageptr,
+ &colPageptr,
+ &ccoPageptr,
+ &datapageptr,
+ &delPageptr,
+ &excPageptr,
+ &expPageptr,
+ &gdiPageptr,
+ &gePageptr,
+ &gflPageptr,
+ &idrPageptr,
+ &ilcPageptr,
+ &inpPageptr,
+ &iopPageptr,
+ &lastPageptr,
+ &lastPrevpageptr,
+ &lcnPageptr,
+ &lcnCopyPageptr,
+ &lupPageptr,
+ &priPageptr,
+ &pwiPageptr,
+ &ciPageidptr,
+ &gsePageidptr,
+ &isoPageptr,
+ &nciPageidptr,
+ &rsbPageidptr,
+ &rscPageidptr,
+ &slPageidptr,
+ &sscPageidptr,
+ &rlPageptr,
+ &rlpPageptr,
+ &ropPageptr,
+ &rpPageptr,
+ &slPageptr,
+ &spPageptr,
+ &rootfragrecptr,
+ &scanPtr,
+ &srVersionPtr,
+ &tabptr,
+ &undopageptr
+ };
+ init_globals_list(tmp, sizeof(tmp)/sizeof(tmp[0]));
+ }
+#endif
}//Dbacc::Dbacc()
Dbacc::~Dbacc()
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index a3880e2df1d..261a0acfa81 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -16,6 +16,7 @@
#define DBACC_C
#include "Dbacc.hpp"
+#include <my_sys.h>
#include <AttributeHeader.hpp>
#include <signaldata/AccFrag.hpp>
@@ -27,6 +28,8 @@
#include <signaldata/FsRemoveReq.hpp>
#include <signaldata/DropTab.hpp>
#include <signaldata/DumpStateOrd.hpp>
+#include <KeyDescriptor.hpp>
+
// TO_DO_RONM is a label for comments on what needs to be improved in future versions
// when more time is given.
@@ -52,8 +55,7 @@ Dbacc::remainingUndoPages(){
// There can not be more than cundopagesize remaining
if (Remaining <= 0){
// No more undolog, crash node
- progError(__LINE__,
- ERR_NO_MORE_UNDOLOG,
+ progError(__LINE__, NDBD_EXIT_NO_MORE_UNDOLOG,
"There are more than 1Mbyte undolog writes outstanding");
}
return Remaining;
@@ -532,7 +534,14 @@ void Dbacc::execNDB_STTOR(Signal* signal)
void Dbacc::execSTTOR(Signal* signal)
{
jamEntry();
- // tstartphase = signal->theData[1];
+ Uint32 tstartphase = signal->theData[1];
+ switch (tstartphase) {
+ case 1:
+ jam();
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
+ break;
+ }
tuserblockref = signal->theData[3];
csignalkey = signal->theData[6];
sttorrysignalLab(signal);
@@ -669,6 +678,20 @@ void Dbacc::execREAD_CONFIG_REQ(Signal* signal)
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
+ Uint32 log_page_size= 0;
+ ndb_mgm_get_int_parameter(p, CFG_DB_UNDO_INDEX_BUFFER,
+ &log_page_size);
+
+ /**
+ * Always set page size in half MBytes
+ */
+ cundopagesize= (log_page_size / sizeof(Undopage));
+ Uint32 mega_byte_part= cundopagesize & 15;
+ if (mega_byte_part != 0) {
+ jam();
+ cundopagesize+= (16 - mega_byte_part);
+ }
+
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_RANGE, &cdirrangesize));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_ARRAY, &cdirarraysize));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_FRAGMENT, &cfragmentsize));
@@ -1037,7 +1060,7 @@ void Dbacc::execACCFRAGREQ(Signal* signal)
// config mismatch - do not crash if release compiled
if (tabptr.i >= ctablesize) {
jam();
- addFragRefuse(signal, 800);
+ addFragRefuse(signal, 640);
return;
}
#endif
@@ -1119,8 +1142,8 @@ void Dbacc::execACCFRAGREQ(Signal* signal)
Uint32 userPtr = req->userPtr;
BlockReference retRef = req->userRef;
rootfragrecptr.p->rootState = ACTIVEROOT;
- AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
+ AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
conf->userPtr = userPtr;
conf->rootFragPtr = rootfragrecptr.i;
conf->fragId[0] = rootfragrecptr.p->fragmentid[0];
@@ -1144,6 +1167,7 @@ void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode)
return;
}//Dbacc::addFragRefuseEarly()
+
void
Dbacc::execDROP_TAB_REQ(Signal* signal){
jamEntry();
@@ -1503,6 +1527,7 @@ void Dbacc::initOpRec(Signal* signal)
operationRecPtr.p->hashValue = signal->theData[3];
operationRecPtr.p->tupkeylen = signal->theData[4];
+ operationRecPtr.p->xfrmtupkeylen = signal->theData[4];
operationRecPtr.p->transId1 = signal->theData[5];
operationRecPtr.p->transId2 = signal->theData[6];
operationRecPtr.p->transactionstate = ACTIVE;
@@ -1541,6 +1566,9 @@ void Dbacc::initOpRec(Signal* signal)
// bit to mark lock operation
operationRecPtr.p->isAccLockReq = (Treqinfo >> 31) & 0x1;
+
+ // undo log is not run via ACCKEYREQ
+ operationRecPtr.p->isUndoLogReq = 0;
}//Dbacc::initOpRec()
/* --------------------------------------------------------------------------------- */
@@ -1614,6 +1642,10 @@ void Dbacc::execACCKEYREQ(Signal* signal)
ndbrequire(operationRecPtr.p->transactionstate == IDLE);
initOpRec(signal);
+ // normalize key if any char attr
+ if (! operationRecPtr.p->isAccLockReq && fragrecptr.p->hasCharAttr)
+ xfrmKeyData(signal);
+
/*---------------------------------------------------------------*/
/* */
/* WE WILL USE THE HASH VALUE TO LOOK UP THE PROPER MEMORY */
@@ -1713,6 +1745,19 @@ void Dbacc::execACCKEYREQ(Signal* signal)
return;
}//Dbacc::execACCKEYREQ()
+void
+Dbacc::xfrmKeyData(Signal* signal)
+{
+ Uint32 table = fragrecptr.p->myTableId;
+ Uint32 dst[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32* src = &signal->theData[7];
+ Uint32 len = xfrm_key(table, src, dst, sizeof(dst) >> 2, keyPartLen);
+ ndbrequire(len); // 0 means error
+ memcpy(src, dst, len << 2);
+ operationRecPtr.p->xfrmtupkeylen = len;
+}
+
void Dbacc::accIsLockedLab(Signal* signal)
{
ndbrequire(csystemRestart == ZFALSE);
@@ -1786,8 +1831,6 @@ void Dbacc::insertExistElemLab(Signal* signal)
/* --------------------------------------------------------------------------------- */
void Dbacc::insertelementLab(Signal* signal)
{
- Uint32 tinsKeyLen;
-
if (fragrecptr.p->createLcp == ZTRUE) {
if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) {
jam();
@@ -1805,46 +1848,9 @@ void Dbacc::insertelementLab(Signal* signal)
}//if
}//if
if (fragrecptr.p->keyLength != operationRecPtr.p->tupkeylen) {
+ // historical
ndbrequire(fragrecptr.p->keyLength == 0);
}//if
- if (fragrecptr.p->keyLength != 0) {
- ndbrequire(operationRecPtr.p->tupkeylen <= 8);
- for (Uint32 i = 0; i < operationRecPtr.p->tupkeylen; i++) {
- jam();
- ckeys[i] = signal->theData[i + 7];
- }//for
- tinsKeyLen = operationRecPtr.p->tupkeylen;
- } else {
- jam();
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- operationRecPtr.p->keyinfoPage = spPageptr.i;
- for (Uint32 i = 0; i < signal->theData[4]; i++) {
- spPageptr.p->word32[i] = signal->theData[i + 7];
- }//for
-
- getLongKeyPage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- slkPageptr = glkPageptr;
- slkCopyPageptr.i = operationRecPtr.p->keyinfoPage;
- ptrCheckGuard(slkCopyPageptr, cpagesize, page8);
- tslkKeyLen = operationRecPtr.p->tupkeylen;
- storeLongKeys(signal);
- ckeys[0] = (slkPageptr.p->word32[ZPOS_PAGE_ID] << 10) + tslkPageIndex;
- tinsKeyLen = ZACTIVE_LONG_KEY_LEN;
- rpPageptr.i = operationRecPtr.p->keyinfoPage;
- ptrCheckGuard(rpPageptr, cpagesize, page8);
- releasePage(signal);
- operationRecPtr.p->keyinfoPage = RNIL;
- }//if
signal->theData[0] = operationRecPtr.p->userptr;
Uint32 blockNo = refToBlock(operationRecPtr.p->userblockref);
@@ -1868,7 +1874,6 @@ void Dbacc::insertelementLab(Signal* signal)
idrPageptr = gdiPageptr;
tidrPageindex = tgdiPageindex;
tidrForward = ZTRUE;
- tidrKeyLen = tinsKeyLen;
idrOperationRecPtr = operationRecPtr;
clocalkey[0] = localKey;
operationRecPtr.p->localdata[0] = localKey;
@@ -2314,14 +2319,14 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
operationRecPtr.p->transactionstate = IDLE;
operationRecPtr.p->operation = ZUNDEFINED_OP;
if(Toperation != ZREAD){
+ rootfragrecptr.i = fragrecptr.p->myroot;
+ ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->m_commit_count++;
if (Toperation != ZINSERT) {
if (Toperation != ZDELETE) {
return;
} else {
jam();
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->noOfElements--;
fragrecptr.p->slack += operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack > fragrecptr.p->slackCheck) {
@@ -2341,8 +2346,6 @@ void Dbacc::execACC_COMMITREQ(Signal* signal)
}//if
} else {
jam(); /* EXPAND PROCESS HANDLING */
- rootfragrecptr.i = fragrecptr.p->myroot;
- ptrCheckGuard(rootfragrecptr, crootfragmentsize, rootfragmentrec);
rootfragrecptr.p->noOfElements++;
fragrecptr.p->slack -= operationRecPtr.p->insertDeleteLen;
if (fragrecptr.p->slack >= (1u << 31)) {
@@ -2460,6 +2463,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
signal->theData[4] = 1; // fake primKeyLen
signal->theData[5] = req->transId1;
signal->theData[6] = req->transId2;
+ // enter local key in place of PK
signal->theData[7] = req->tupAddr;
EXECUTE_DIRECT(DBACC, GSN_ACCKEYREQ, signal, 8);
// translate the result
@@ -2484,26 +2488,6 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
*sig = *req;
return;
}
- operationRecPtr.i = req->accOpPtr;
- ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (fragrecptr.p->keyLength == 0 &&
- // should test some state variable
- operationRecPtr.p->elementPage != RNIL) {
- jam();
- // re-compute long key vars
- Page8Ptr tPageptr;
- tPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(tPageptr, cpagesize, page8);
- Uint32 tKeyptr =
- operationRecPtr.p->elementPointer +
- operationRecPtr.p->elementIsforward *
- (ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
- tslcPageIndex = tPageptr.p->word32[tKeyptr] & 0x3ff;
- tslcPagedir = tPageptr.p->word32[tKeyptr] >> 10;
- searchLongKey(signal, false);
- }
if (lockOp == AccLockReq::Unlock) {
jam();
// do unlock via ACC_COMMITREQ (immediate)
@@ -2857,14 +2841,6 @@ void Dbacc::insertContainer(Signal* signal)
idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */
tidrIndex += tidrForward;
}//for
- guard26 = tidrKeyLen - 1;
- arrGuard(guard26, 8);
- for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) {
- dbgWord32(idrPageptr, tidrIndex, ckeys[tidrInputIndex]);
- arrGuard(tidrIndex, 2048);
- idrPageptr.p->word32[tidrIndex] = ckeys[tidrInputIndex]; /* INSERTS TUPLE KEY */
- tidrIndex += tidrForward;
- }//for
tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6;
tidrContLen = tidrContLen >> 6;
dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen);
@@ -3198,1215 +3174,6 @@ void Dbacc::seizeRightlist(Signal* signal)
increaselistcont(signal);
}//Dbacc::seizeRightlist()
-
-//---------------------------------------------------------------------------------
-// ALLOC_SPECIFIC_LONG_OVERFLOW_PAGE
-//
-// DESCRIPTION: ALLOCATES A LONG OVER FLOW PAGE AND PUTS IT IN A SPECIFIED
-// DIRINDEX. THIS IS TO SUPPORT AN UNDO_DELETE AFTER AN
-// UNDO_INSERT ON THE SAME LONG KEY IN A LCP.
-// UNDO_INSERT ONLY HAVE A REFERENCE TO THE KEY AND TO MAKE
-// IT POSSIBLE TO DELETE THE KEY, THE REFERENCE MUST BE
-// ACCURATE, WHICH MEANS THE KEY MUST BE SAVED ON THE SAME
-// PLACE IT WAS DELETED FROM.
-//---------------------------------------------------------------------------------
-void Dbacc::allocSpecificLongOverflowPage(Signal* signal)
-{
- DirRangePtr aloDirRangePtr;
- DirectoryarrayPtr aloOverflowDirptr;
-
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocSpecificLongOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }
-
- if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- }
-
- tmpP = taslpDirIndex;
- aloDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
-
- if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }
- aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- } else {
- jam();
- sdDirptr.i = RNIL;
- ptrNull(sdDirptr);
- }
-
- aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray);
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }//if
-
- if (aloOverflowDirptr.p->pagep[tmpP] != RNIL) {
- jam();
- sendSystemerror(signal);
- return;
- }
-
- aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i;
- iloPageptr.p = spPageptr.p;
- iloPageptr.i = spPageptr.i;
- tiloIndex = taslpDirIndex;
- initLongOverpage(signal);
- aslpPageptr.i = spPageptr.i;
- aslpPageptr.p = spPageptr.p;
-}//Dbacc::allocSpecificLongOverflowPage
-
-/* --------------------------------------------------------------------------------- */
-/* ALLOC_LONG_OVERFLOW_PAGE */
-/* DESCRIPTION: */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::allocLongOverflowPage(Signal* signal)
-{
- DirRangePtr aloDirRangePtr;
- DirectoryarrayPtr aloOverflowDirptr;
- OverflowRecordPtr aloOverflowRecPtr;
- Uint32 taloIndex;
-
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocLongOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }//if
- if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- }//if
- if (fragrecptr.p->firstFreeDirindexRec != RNIL) {
- jam();
- aloOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
- ptrCheckGuard(aloOverflowRecPtr, coverflowrecsize, overflowRecord);
- troOverflowRecPtr.p = aloOverflowRecPtr.p;
- takeRecOutOfFreeOverdir(signal);
- taloIndex = aloOverflowRecPtr.p->dirindex;
- rorOverflowRecPtr = aloOverflowRecPtr;
- releaseOverflowRec(signal);
- } else {
- jam();
- taloIndex = fragrecptr.p->lastOverIndex;
- fragrecptr.p->lastOverIndex++;
- }//if
- tmpP = taloIndex;
- aloDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- } else {
- jam();
- sdDirptr.i = RNIL;
- ptrNull(sdDirptr);
- }//if
- aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray);
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i;
- iloPageptr = spPageptr;
- tiloIndex = taloIndex;
- initLongOverpage(signal);
- alpPageptr = spPageptr;
- ipaPagePtr = spPageptr;
- tipaArrayPos = 3;
- insertPageArrayList(signal);
-}//Dbacc::allocLongOverflowPage()
-
-/* --------------------------------------------------------------------------------- */
-/* GET_LONG_KEY_PAGE */
-/* DESCRIPTION: SEARCH FOR A FREE OVERFLOW PAGE TO STORE A LONG KEY. */
-/* LONG_KEY_PAGE_PTR IS RETURNED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::getLongKeyPage(Signal* signal)
-{
- LongKeyPage *glkPage;
-
- jam();
-
- Uint32 tglkLongIndex = 0;
-
- ndbrequire(operationRecPtr.p->tupkeylen <= ZWORDS_IN_PAGE - ZHEAD_SIZE);
-
- // Do not look in longKeyPageArray[tglkLongIndex] where the pages are to small.
- if(operationRecPtr.p->tupkeylen < 128) {
- jam();
- tglkLongIndex = 0;
- } else {
- jam();
- tglkLongIndex = (operationRecPtr.p->tupkeylen - 128) / 512;
- }//if
-
- // Go through the longKeyPageArray and search for a page.
- for (; tglkLongIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; tglkLongIndex++) {
- jam();
- glkPageptr.i = fragrecptr.p->longKeyPageArray[tglkLongIndex];
-
- if (glkPageptr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(glkPageptr, cpagesize, page8);
- glkPage = (LongKeyPage *) &glkPageptr.p->word32[0];
-
- // Check page if there is enough memory available. Accept only page
- // with free_area > tupkeylen, this leaves at least one word for eventually
- // an increase in the index area.
- if (glkPage->header.freeArea > operationRecPtr.p->tupkeylen){
- // The page found is OK
- jam();
- return;
- } else {
- // Not enough space in page, look in the next page if not RNIL,
- // otherwise continue with for-loop.
- jam();
- glkPageptr.i = glkPage->header.nextPage;
- }
- }//do
- while (glkPageptr.i != RNIL);
- }//if
- }//for
-
- // No page with enough space was available, allocate a new page!
- jam();
- allocLongOverflowPage(signal);
- glkPageptr = alpPageptr;
-}//Dbacc::getLongKeyPage()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_LONG_OVERPAGE */
-/* INPUT. ILO_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
-/* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
-/* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initLongOverpage(Signal* signal)
-{
- iloPageptr.p->word32[ZPOS_PAGE_ID] = tiloIndex;
- iloPageptr.p->word32[ZPOS_PAGE_TYPE] = ZLONG_PAGE_TYPE << ZPOS_PAGE_TYPE_BIT;
- iloPageptr.p->word32[ZPOS_NO_ELEM_IN_PAGE] = 0;
- iloPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- iloPageptr.p->word32[ZPOS_FREE_AREA_IN_PAGE] = ZWORDS_IN_PAGE - ZHEAD_SIZE;
- iloPageptr.p->word32[ZPOS_LAST_INDEX] = 0;
- iloPageptr.p->word32[ZPOS_INSERT_INDEX] = ZHEAD_SIZE;
- iloPageptr.p->word32[ZPOS_ARRAY_POS] = ZDEFAULT_LIST;
- iloPageptr.p->word32[ZPOS_NEXT_FREE_INDEX] = 0;
- iloPageptr.p->word32[ZPOS_NEXT_PAGE] = RNIL;
- iloPageptr.p->word32[ZPOS_PREV_PAGE] = RNIL;
- iloPageptr.p->word32[12] = 0;
- iloPageptr.p->word32[13] = 0;
- iloPageptr.p->word32[14] = 0;
- iloPageptr.p->word32[15] = 0;
- // Initialize free indexes
- for (int i = 1; i < (ZWORDS_IN_PAGE - ZHEAD_SIZE); i++)
- iloPageptr.p->word32[ZWORDS_IN_PAGE - i] = i + 1;
-}//Dbacc::initLongOverpage()
-
-//---------------------------------------------------------------------------------
-// STORE_LONG_KEYS_AT_POS
-//
-// INPUT: SLKAP_PAGEPTR
-// SLKAP_COPY_PAGEPTR
-// TSLKAP_KEY_LEN
-// TSLKAP_PAGE_INDEX
-//
-// DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE AT A
-// SPECIFIC POSITION. THIS FUNCTION IS USED BY UNDO_DELETE.
-//---------------------------------------------------------------------------------
-void Dbacc::storeLongKeysAtPos(Signal* signal)
-{
- Uint32 tslkapHighestIndex;
- Uint32 tslkapLastSize;
- Uint32 tslkapInsertIndex;
- Uint32 tslkapIndexIncreaseSize;
- Uint32 tslkapTmp;
-
- LongKeyPage *slkapPage;
-
- jam();
- slkapPage = (LongKeyPage *) &slkapPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(slkapPageptr.i, "storeLongKeysAtPos");
-#endif
-
- // if (csystemRestart != ZTRUE) {
- if (cundoLogActive != ZTRUE) {
- //-------------------------------------------------------------
- // This function is only allowed to be called during
- // undolog execution.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- if (slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] >> 16 != 0 ) {
- //-------------------------------------------------------------
- // The index should be empty, we have a serious problem.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- //-------------------------------------------------------------
- // Calculate some variables to use later.
- //-------------------------------------------------------------
- tslkapHighestIndex = slkapPage->header.highestIndex;
- tslkapPageIndex > tslkapHighestIndex ?
- tslkapIndexIncreaseSize = tslkapPageIndex - tslkapHighestIndex :
- tslkapIndexIncreaseSize = 0;
-
- slkapPage->header.highestIndex += tslkapIndexIncreaseSize;
-
- if ((slkapPage->header.freeArea - tslkapIndexIncreaseSize)
- < tslkapKeyLen) {
- //-------------------------------------------------------------
- // Not enough area in the page, a serious problem.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- //-------------------------------------------------------------
- // Fix the free index list. We might put in a key in the
- // middle of the list, so we must fix the free list and the
- // free index pointers.
- //-------------------------------------------------------------
- slkapPage->header.nextFreeIndex = 0;
-
- for (Uint32 i = tslkapHighestIndex + tslkapIndexIncreaseSize; i > 0; i--) {
- if (i == tslkapPageIndex) {
- // The key index shall not be in the free list.
- continue;
- }
-
- if (slkapPage->word32[ZWORDS_IN_PAGE - i] >> 16 == 0 ) {
- // Go through all empty indexes.
- slkapPage->word32[ZWORDS_IN_PAGE - i] = slkapPage->header.nextFreeIndex;
- arrGuard(i, 2048);
- slkapPage->header.nextFreeIndex = i;
- }
- }
-
- //-------------------------------------------------------------
- // Decrement the free area in page according to the above
- // increase in index size.
- //-------------------------------------------------------------
- slkapPage->header.freeArea -= tslkapIndexIncreaseSize;
-
- tslkapLastSize = ZWORDS_IN_PAGE - slkapPage->header.highestIndex
- - slkapPage->header.insertPos;
-
- //-------------------------------------------------------------
- // Check if we have to reorganize the page.
- //-------------------------------------------------------------
- if (tslkapLastSize >= tslkapKeyLen) {
- jam();
- } else {
- jam();
- relpPageptr.p = slkapPageptr.p;
- reorgLongPage(signal);
- }
-
- //-------------------------------------------------------------
- // Insert the key and update page attributes.
- //-------------------------------------------------------------
- jam();
- // Increase the number of element in the page.
- slkapPage->header.noOfElements++;
- jam();
- // Put in the key reference into the index. The reference
- // consists of key length and insert position.
- arrGuard(ZWORDS_IN_PAGE - tslkapPageIndex, 2048);
- slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] =
- slkapPage->header.insertPos | (tslkapKeyLen << 16);
- jam();
- // Increase the key insert position.
- tslkapInsertIndex = slkapPage->header.insertPos;
- slkapPage->header.insertPos += tslkapKeyLen;
- jam();
- // Decrease the free area.
- slkapPage->header.freeArea -= tslkapKeyLen;
- jam();
-
- // Update pageArrayPos. insertPageArrayList() called from execACC_OVER_REC
- // needs this value.
- if (slkapPage->header.freeArea < 128) {
- jam();
- slkapPage->header.pageArrayPos = 4;
- } else {
- jam();
- slkapPage->header.pageArrayPos = (slkapPage->header.freeArea - 128) / 512;
- }//if
-
- // Store the actual key at the insert position.
- Uint32 guard27 = tslkapKeyLen - 1;
- arrGuard(guard27 + tslkapInsertIndex, 2048);
- for (tslkapTmp = 0; tslkapTmp <= guard27; tslkapTmp++) {
- jam();
- slkapPage->word32[tslkapTmp + tslkapInsertIndex] = slkapCopyPageptr.p->word32[tslkapTmp];
- }//for
-}//Dbacc::storeLongKeysAtPos
-
-/* --------------------------------------------------------------------------------- */
-/* STORE_LONG_KEYS */
-/* INPUT: SLK_PAGEPTR */
-/* SLK_COPY_PAGEPTR */
-/* TSLK_KEY_LEN */
-/* OUTPUT: TSLK_PAGE_INDEX */
-/* */
-/* DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::storeLongKeys(Signal* signal)
-{
- Uint32 tslkLastSize;
- Uint32 tslkInsertIndex;
- Uint32 tslkArrayPos;
- Uint32 tslkTmp;
- Uint32 guard27;
- LongKeyPage *slkPage;
-
- jam();
- slkPage = (LongKeyPage *) &slkPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys1");
-#endif
-
- // Accept only page with free_area > tupkeylen, this leaves at least
- // one word for eventually an increase in the index area.
- ndbrequire(slkPage->header.freeArea > tslkKeyLen);
-
- dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex);
- dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos);
-
- tslkLastSize = ZWORDS_IN_PAGE - slkPage->header.highestIndex - slkPage->header.insertPos;
-
- if (tslkLastSize > operationRecPtr.p->tupkeylen) {
- // WE DO NOT NEED TO REORGANIZE THE PAGE TO INSERT THE NEW KEY. IT FITS INTO THE
- // SIZE REMAINING AT THE END.
- jam();
- } else {
- // THE KEY FITS INTO THE PAGE BUT ONLY AFTER REORGANISING THE PAGE.
- jam();
- relpPageptr.p = slkPageptr.p;
- reorgLongPage(signal);
- }//if
-
- if (slkPage->header.nextFreeIndex == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/
- /* --------------------------------------------------------------------------------- */
- tslkPageIndex = slkPage->header.highestIndex + 1;
- } else {
- jam();
- tslkPageIndex = slkPage->header.nextFreeIndex;
- }//if
-
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* ON LONG PAGES WE USE A PHYSIOLOGICAL LOGGING SCHEME. THIS MEANS THAT WE ONLY NEED*/
- /* TO SPECIFY WHICH INDEX TO DELETE IN ORDER TO UNDO THE CHANGES WE DO. THE */
- /* POSSIBLE REORGANISATION DO NOT CHANGE THE LOGICAL LAYOUT OF THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- datapageptr.p = slkPageptr.p;
- cundoElemIndex = tslkPageIndex;
- cundoinfolength = 0;
- undoWritingProcess(signal);
- }//if
-
- if (slkPage->header.nextFreeIndex == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/
- /* --------------------------------------------------------------------------------- */
- dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex + 1);
- slkPage->header.highestIndex++;
- ndbrequire(slkPage->header.insertPos < (ZWORDS_IN_PAGE - slkPage->header.highestIndex));
- // Reset index. We have already checked that we can increase "highestIndex" value
- // without overwriting the data part.
- slkPage->word32[ZWORDS_IN_PAGE - slkPage->header.highestIndex] = 0;
- dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - 1);
- slkPage->header.freeArea--;
- } else {
- jam();
- dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex]);
- arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048);
- arrGuard(slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex], 2048);
-
- slkPage->header.nextFreeIndex = slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex];
- if(slkPage->header.nextFreeIndex > slkPage->header.highestIndex){
- slkPage->header.nextFreeIndex = 0;
- dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->header.nextFreeIndex);
- }
- }//if
-
- dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, tslkKeyLen);
- dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, slkPage->header.insertPos);
- arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048);
- slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex] =
- slkPage->header.insertPos | (tslkKeyLen << 16);
-
- dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos);
- tslkInsertIndex = slkPage->header.insertPos;
- slkPage->header.insertPos += tslkKeyLen;
-
- dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - tslkKeyLen);
- slkPage->header.freeArea = slkPage->header.freeArea - tslkKeyLen;
- if (slkPage->header.freeArea < 128) {
- jam();
- tslkArrayPos = 4;
- } else {
- jam();
- tslkArrayPos = (slkPage->header.freeArea - 128) / 512;
- }//if
-
- if (tslkArrayPos != slkPage->header.pageArrayPos) {
- jam();
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE ONLY HANDLE THE LISTS WHEN WE ARE NOT IN A SYSTEM RESTART. */
- /* --------------------------------------------------------------------------------- */
- rfpPageptr = slkPageptr;
- trfpArrayPos = slkPage->header.pageArrayPos;
- removeFromPageArrayList(signal);
- ipaPagePtr = slkPageptr;
- tipaArrayPos = tslkArrayPos;
- slkPage->header.pageArrayPos = tipaArrayPos;
- if (tslkArrayPos != 4) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE WILL STILL BE ON ONE OF THE FREE LISTS SINCE AT LEAST 128 * 4 */
- /* BYTES OF FREE SPACE REMAINS ON THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- insertPageArrayList(signal);
- }//if
- } else {
- // This should never happen. Should use storeLongKeysAtPos() instead when executing
- // undolog.
- ndbrequire(false);
- }
- }//if
- /* --------------------------------------------------------------------------------- */
- /* INCREASE THE NUMBER OF ELEMENTS IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(slkPageptr, ZPOS_NO_ELEM_IN_PAGE, slkPage->header.noOfElements + 1);
- slkPage->header.noOfElements++;
-
- guard27 = tslkKeyLen - 1;
- arrGuard(guard27 + tslkInsertIndex, 2048);
- for (tslkTmp = 0; tslkTmp <= guard27; tslkTmp++) {
- dbgWord32(slkPageptr, tslkTmp + tslkInsertIndex, slkCopyPageptr.p->word32[tslkTmp]);
- slkPage->word32[tslkTmp + tslkInsertIndex] = slkCopyPageptr.p->word32[tslkTmp];
- }//for
-
- // Used by abortoperation() in case of an abort.
- operationRecPtr.p->longPagePtr = slkPageptr.i;
-
- // This is for an eventual LCP start in the middle of this locked operation.
- operationRecPtr.p->longKeyPageIndex = tslkPageIndex;
-
-#ifdef VM_TRACE
- if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "storeLongKeys");
- checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys2");
-#endif
-
-}//Dbacc::storeLongKeys()
-
-/* --------------------------------------------------------------------------------- */
-/* REORGANIZE THE PAGE BY COPYING IT TEMPORARILY TO A NEW AREA AND THEN SIMPLY */
-/* PUTTING THE OBJECTS BACK ON THE PAGE IN THE SAME ORDER AS THEY ARE PLACED IN THE */
-/* INDEX. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::reorgLongPage(Signal* signal)
-{
- Uint32 indexStartPos;
- Uint32 pagePos;
- Uint32 pagePos2;
- Uint32 indexNo;
- Uint32 insertPos;
- Uint32 indexValue;
- Uint32 keyLength;
- Uint32 keyPos;
- Uint32 keyEndPos;
- LongKeyPage *reOrgPage;
-
- ptrGuard(relpPageptr);
- reOrgPage = (LongKeyPage *) &relpPageptr.p->word32[0];
-
- dbgWord32(relpPageptr, ZPOS_LAST_INDEX, reOrgPage->header.highestIndex);
- indexStartPos = ZWORDS_IN_PAGE - reOrgPage->header.highestIndex;
-
- // Copy key data part of page to a temporary page.
- for (pagePos = ZHEAD_SIZE; pagePos < indexStartPos; pagePos++) {
- jam();
- arrGuard(pagePos, 2048);
- ckeys[pagePos] = reOrgPage->word32[pagePos];
- }//for
-
- insertPos = ZHEAD_SIZE;
-
- // Walk through all the indexes.
- for (indexNo = 1; indexNo <= reOrgPage->header.highestIndex; indexNo++) {
- jam();
- arrGuard(ZWORDS_IN_PAGE - indexNo, 2048);
- dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, reOrgPage->word32[ZWORDS_IN_PAGE - indexNo]);
- indexValue = reOrgPage->word32[ZWORDS_IN_PAGE - indexNo];
-
- if ((indexValue >> 16) != 0) {
- // The index contains a reference to a key.
- jam();
- keyPos = indexValue & 0xffff;
- keyLength = indexValue >> 16;
- dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, insertPos + (keyLength << 16));
- arrGuard(ZWORDS_IN_PAGE - indexNo, 2048);
-
- // Refresh the index data with the new key start position in the data part.
- reOrgPage->word32[ZWORDS_IN_PAGE - indexNo] = insertPos + (keyLength << 16);
- keyEndPos = keyPos + keyLength;
- arrGuard(keyEndPos, 2048);
-
- // Copy the key from the temporary page
- // to the insert position at original page.
- for (pagePos2 = keyPos; pagePos2 < keyEndPos; pagePos2++, insertPos++) {
- jam();
- dbgWord32(relpPageptr, insertPos, ckeys[pagePos2]);
- arrGuard(insertPos, 2048);
- arrGuard(pagePos2, 2048);
- reOrgPage->word32[insertPos] = ckeys[pagePos2];
- }//for
- }//if
- }//for
- dbgWord32(relpPageptr, ZPOS_INSERT_INDEX, insertPos);
- reOrgPage->header.insertPos = insertPos;
-}//Dbacc::reorgLongPage()
-
-
-/* --------------------------------------------------------------------------------- */
-/* DELETE_LONG_KEY */
-/* INPUT: DLK_PAGEPTR PAGE POINTER OF DELETED KEY OBJECT */
-/* TDLK_LOGICAL_PAGE_INDEX LOGICAL PAGE INDEX OF DELETED KEY OBJECT */
-/* */
-/* DESCRIPTION: DELETE AN ELEMENT OF A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::deleteLongKey(Signal* signal)
-{
- Uint32 tdlkLastIndex;
- Uint32 tdlkNextPosition;
- Uint32 tdlkFreeArea;
- Uint32 tdlkArrayPos;
- Uint32 tdlkOldArrayPos;
- LongKeyPage *dlkPage;
-
- jam();
- dlkPage = (LongKeyPage *) &dlkPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey1");
-#endif
-
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] >> 16);
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] & 0xffff);
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
-
- const Uint32 tdlkIndexValue = dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex];
- const Uint32 tdlkKeyLen = tdlkIndexValue >> 16;
- const Uint32 tdlkPhysPageIndex = tdlkIndexValue & 0xffff;
-
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE LOG THE DELETE LONG KEY BY LOGGING THE DELETED KEY AND ITS LOGICAL INDEX.*/
- /* --------------------------------------------------------------------------------- */
- datapageptr.p = dlkPageptr.p;
- cundoElemIndex = tdlkLogicalPageIndex;
- cundoinfolength = tdlkKeyLen;
- undoWritingProcess(signal);
- }//if
- /* --------------------------------------------------------------------------------- */
- /* DECREASE THE NUMBER OF ELEMENTS IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_NO_ELEM_IN_PAGE, dlkPage->header.noOfElements - 1);
- dlkPage->header.noOfElements--;
-
- arrGuard(dlkPage->header.noOfElements, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
-
- /* --------------------------------------------------------------------------------- */
- /* INCREASE THE FREE AREA IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea + tdlkKeyLen);
- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, dlkPage->header.highestIndex);
-
- dlkPage->header.freeArea += tdlkKeyLen;
-
- if (dlkPage->header.noOfElements == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE IS NOW EMPTY, WE CAN RELEASE IT. */
- /* --------------------------------------------------------------------------------- */
- if (dlkPage->header.freeArea !=
- (ZWORDS_IN_PAGE - ZHEAD_SIZE - dlkPage->header.highestIndex )) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* SOME AREA IN THE PAGE IS STILL LEFT BUT NO ELEMENTS, INCONSISTENT */
- /* --------------------------------------------------------------------------------- */
- sendSystemerror(signal);
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE REMOVE THE PAGE FROM THE LIST OF FREE LONG PAGES. THERE IS NO RISK THAT IT */
- /* DID NOT BELONG TO ANY SINCE IT IS NOT ALLOWED TO HAVE THAT LARGE KEYS. */
- /* --------------------------------------------------------------------------------- */
-
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */
- /* --------------------------------------------------------------------------------- */
- // REMOVEFROMLIST is done by releaseLongPage(). EDTJAMO.
- // rfpPageptr = dlkPageptr;
- // trfpArrayPos = dlkPage->header.pageArrayPos;
- // removeFromPageArrayList(signal, "deleteLongKey");
- rlopPageptr = dlkPageptr;
- releaseLongPage(signal);
- return;
- } else {
- // Must remove reference to the removed key, otherwise left in index. EDTJAMO.
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
- arrGuard(tdlkLogicalPageIndex, 2048);
-
- tdlkNextPosition = dlkPage->header.nextFreeIndex;
- dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex;
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition);
- dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition;
- }
- } else {
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE IS NOT EMPTY SO WE WILL REMOVE THE KEY OBJECT AND UPDATE THE */
- /* HEADER INFORMATION AND PLACE THE PAGE IN THE PROPER PAGE LIST. */
- /* --------------------------------------------------------------------------------- */
- tdlkLastIndex = dlkPage->header.highestIndex;
- arrGuard(ZWORDS_IN_PAGE - tdlkLastIndex, 2048);
- if (tdlkLastIndex == tdlkLogicalPageIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE DELETE THE LAST PAGE INDEX SO WE NEED TO UPDATE THE VALUE. WE MOVE */
- /* BACKWARDS UNTIL WE EITHER FIND A USED INDEX OR THAT WE COME TO INDEX ZERO. */
- /* --------------------------------------------------------------------------------- */
- tdlkLastIndex--;
- while( (tdlkLastIndex > 1) &&
- (dlkPage->word32[ZWORDS_IN_PAGE - tdlkLastIndex] >> 16) == 0 ) {
- jam();
- tdlkLastIndex--;
- }
- //-----------------------------------------------------
- // Reorganize the rest of the index. Set up the free
- // list and the free index.
- //-----------------------------------------------------
- UintR dlkTmp = tdlkLastIndex;
- dlkPage->header.nextFreeIndex = 0;
- while( dlkTmp > 0) {
- if ( (dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] >> 16) == 0 ) {
- jam();
- dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] = dlkPage->header.nextFreeIndex;
- arrGuard(dlkTmp, 2048);
- dlkPage->header.nextFreeIndex = dlkTmp;
- }
- dlkTmp--;
- }
- //-----------------------------------------------------
- // Update free area in page and last index.
- //-----------------------------------------------------
- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, tdlkLastIndex);
- dlkPage->header.highestIndex = tdlkLastIndex;
- dlkPage->header.freeArea = tdlkLogicalPageIndex +
- dlkPage->header.freeArea - tdlkLastIndex;
- tdlkNextPosition = 0;
- } else {
- if (dlkPage->header.highestIndex > tdlkLogicalPageIndex) {
- jam();
- tdlkNextPosition = dlkPage->header.nextFreeIndex;
- dbgWord32(dlkPageptr, ZPOS_NEXT_FREE_INDEX, tdlkLogicalPageIndex);
- arrGuard(tdlkLogicalPageIndex, 2048);
- dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* LOGICAL PAGE INDEX LARGER THAN LARGEST INDEX, INCONSISTENT. */
- /* --------------------------------------------------------------------------------- */
- sendSystemerror(signal);
- return; // Just to keep compiler happy
- }//if
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE INSERT ZERO INTO THE LENGTH PART TO INDICATE A FREE INDEX POSITION. */
- /* WE INSERT A POINTER TO THE NEXT FREE INDEX TO AS TO PUT IT INTO A FREE */
- /* LIST OF INDEX POSITIONS. WE ONLY DO SO IF IT WAS NOT THE LAST INDEX. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition);
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
- dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition;
- if (dlkPage->header.insertPos == (tdlkPhysPageIndex + tdlkKeyLen)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS ENTRY IS THE LAST ON THE PAGE SO WE WILL UPDATE THE INSERT INDEX */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_INSERT_INDEX, tdlkPhysPageIndex);
- dlkPage->header.insertPos = tdlkPhysPageIndex;
- }//if
- }//if
- dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea);
- tdlkFreeArea = dlkPage->header.freeArea;
- ndbrequire(tdlkFreeArea <= (ZWORDS_IN_PAGE - ZHEAD_SIZE));
- if (tdlkFreeArea < 128) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* FREE AREA IS STILL LESS THAN 128 WORDS SO IT SHOULD NOT BE PLACED IN ANY OF THE */
- /* FREE LISTS. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos);
- ndbrequire(dlkPage->header.pageArrayPos == 4);
- } else {
- jam();
- // Calculate an eventually new arraypos.
- dbgWord32(dlkPageptr, 0, (tdlkFreeArea - 128) / 512);
- tdlkArrayPos = (tdlkFreeArea - 128) / 512;
-
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos);
- tdlkOldArrayPos = dlkPage->header.pageArrayPos;
- if (tdlkArrayPos != tdlkOldArrayPos) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE NEW MEMORY AREA HAS ENABLED THE PAGE TO MOVE TO A NEW FREE PAGE LIST */
- /* --------------------------------------------------------------------------------- */
- rfpPageptr = dlkPageptr;
- trfpArrayPos = tdlkOldArrayPos;
- if (tdlkOldArrayPos != 4) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THERE WAS A FREE PAGE LIST TO REMOVE THE PAGE FROM. IF FREE SPACE IS LESS THAN */
- /* 128 BYTES THEN IT IS NOT ON ANY FREE LIST. */
- /* --------------------------------------------------------------------------------- */
- removeFromPageArrayList(signal);
- }//if
- dlkPage->header.pageArrayPos = tdlkArrayPos;
- ipaPagePtr = dlkPageptr;
- tipaArrayPos = tdlkArrayPos;
- insertPageArrayList(signal);
- }//if
- } else {
- // Update pageArrayPos. We are in a SR, executing undolog, insertPageArrayList() called
- // from execACC_OVER_REC needs this value later.
- dlkPage->header.pageArrayPos = tdlkArrayPos;
- }
- }//if
-#ifdef VM_TRACE
- if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "deleteLongKey");
- checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey2");
-#endif
-}//Dbacc::deleteLongKey()
-
-
-void Dbacc::checkIndexInLongKeyPage(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- LongKeyPage *page;
- Uint32 indexNo;
- Uint32 indexValue;
- Uint32 keyLength;
- Uint32 keyPos;
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- // Check the header variables.
- if (page->header.nextFreeIndex > 2048 ||
- page->header.highestIndex > 2048 ||
- page->header.insertPos > 2048 ||
- page->header.freeArea > 2048 ||
- page->header.noOfElements > 225) {
- ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl
- << " pagePtr.i = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Walk through all the indexes.
- for (indexNo = 1; indexNo <= page->header.highestIndex; indexNo++) {
- jam();
- indexValue = page->word32[ZWORDS_IN_PAGE - indexNo];
-
- if ((indexValue >> 16) == 0) {
- ; // key length is 0, means no key reference at this position in index.
- } else {
- // The index contains a reference to a key.
- jam();
- keyPos = indexValue & 0xffff;
- keyLength = indexValue >> 16;
- if (keyPos >= ZWORDS_IN_PAGE || keyLength >= ZWORDS_IN_PAGE) {
- jam();
- ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl
- << " keyPos = " << keyPos << endl
- << " keyLength = " << keyLength << endl
- << " page->header.noOfElements = " << page->header.noOfElements << endl
- << " page->header.freeArea = " << page->header.freeArea << endl
- << " indexNo = " << indexNo << endl
- << " page->header.highestIndex = " << page->header.highestIndex << endl;
- ndbrequire(false);
- }
- }
- }
-}//Dbacc::checkIndexInLongKeyPage
-
-
-/* --------------------------------------------------------------------------------- */
-/* REMOVE A PAGE FROM THE PAGE ARRAY LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::removeFromPageArrayList(Signal* signal)
-{
- Page8Ptr rfpPrevPageptr;
- Page8Ptr rfpNextPageptr;
- LongKeyPage *page;
- LongKeyPage *prevPage;
- LongKeyPage *nextPage;
-
- jam();
-
-#ifdef VM_TRACE
- checkPageB4Remove(rfpPageptr.i, "removeFromPageArrayList");
-#endif
-
- page = (LongKeyPage *) &rfpPageptr.p->word32[0];
-
- if (page->header.prevPage == RNIL) {
- jam();
- arrGuard(trfpArrayPos, 4);
- // This page was first in list, remove reference
- // to this page from the start of the list.
- ndbrequire(fragrecptr.p->longKeyPageArray[trfpArrayPos] == rfpPageptr.i);
- fragrecptr.p->longKeyPageArray[trfpArrayPos] = page->header.nextPage;
- } else {
- jam();
- rfpPrevPageptr.i = page->header.prevPage;
- ptrCheckGuard(rfpPrevPageptr, cpagesize, page8);
- prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0];
- // This page wasn't first in list, remove reference
- // to this page from the previous page.
- ndbrequire(prevPage->header.nextPage == rfpPageptr.i);
- prevPage->header.nextPage = page->header.nextPage;
- }//if
-
- if (page->header.nextPage != RNIL) {
- jam();
- rfpNextPageptr.i = page->header.nextPage;
- ptrCheckGuard(rfpNextPageptr, cpagesize, page8);
- nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0];
- // This page wasn't last in list, remove reference
- // to this page from the next page.
- ndbrequire(nextPage->header.prevPage == rfpPageptr.i);
- nextPage->header.prevPage = page->header.prevPage;
- // Remove reference to next page in list.
- page->header.nextPage = RNIL;
- }//if
-
- // This couldn't be set until now.
- // Remove reference to previous page in list.
- page->header.prevPage = RNIL;
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "removeFromPageArrayList");
-#endif
-}//Dbacc::removeFromPageArrayList()
-
-/* --------------------------------------------------------------------------------- */
-/* INSERT A PAGE INTO THE PAGE ARRAY LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::insertPageArrayList(Signal* signal)
-{
- Page8Ptr ipaNextPagePtr;
- LongKeyPage *page;
- LongKeyPage *nextPage;
-
- jam();
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "insertPageArrayList1");
- checkPageB4Insert(ipaPagePtr.i, "insertPageArrayList1");
-#endif
-
- page = (LongKeyPage *) &ipaPagePtr.p->word32[0];
-
- arrGuard(tipaArrayPos, 4);
-
- if (fragrecptr.p->longKeyPageArray[tipaArrayPos] != RNIL) {
- jam();
- ipaNextPagePtr.i = fragrecptr.p->longKeyPageArray[tipaArrayPos];
- ptrCheckGuard(ipaNextPagePtr, cpagesize, page8);
- nextPage = (LongKeyPage *) &ipaNextPagePtr.p->word32[0];
-
- // A page already existed in the list, add reference
- // to this page in the next page.
- nextPage->header.prevPage = ipaPagePtr.i;
- }//if
-
- page->header.prevPage = RNIL;
- page->header.nextPage = fragrecptr.p->longKeyPageArray[tipaArrayPos];
- page->header.pageArrayPos = tipaArrayPos;
-
- fragrecptr.p->longKeyPageArray[tipaArrayPos] = ipaPagePtr.i;
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "insertPageArrayList2");
-#endif
-}//Dbacc::insertPageArrayList()
-
-// --------------------------------------------------------------------------------- */
-// Check the page array list.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageArrayList(Signal* signal, const char *calledFrom)
-{
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- LongKeyPage *page;
- Uint32 prevPage;
-
- // Go through the longKeyPageArray and search for a page.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
- prevPage = RNIL;
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- if ((page->header.freeArea >= 128) &&
- (((page->header.freeArea - 128) / 512) == page->header.pageArrayPos) &&
- (pageArrayIndex == page->header.pageArrayPos) &&
- (page->header.prevPage == prevPage)) {
- // The page found is OK, test next page.
- prevPage = pagePtr.i;
- pagePtr.i = page->header.nextPage;
- jam();
- } else {
- jam();
- ndbout << " ERROR in checkPageArrayList, called from " << calledFrom << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " prevPage = " << prevPage << endl
- << " pageArrayIndex = " << pageArrayIndex << endl;
- printoutInfoAndShutdown(page);
- }
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-}//Dbacc::checkPageArrayList()
-
-// --------------------------------------------------------------------------------- */
-// Check the page to put into the pageArrayList.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Insert(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- LongKeyPage *page;
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- if ((page->header.nextPage != RNIL) ||
- (page->header.prevPage != RNIL)) {
- jam();
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " page->header.nextPage = " << page->header.nextPage << endl
- << " page->header.prevPage = " << page->header.prevPage << endl;
- ndbrequire(false);
- }
-
- // Page should not be inserted in list if free area is less than 512 byte.
- if (page->header.freeArea < 128) {
- jam();
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " Page has to little free area to be in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " tipaArrayPos = " << tipaArrayPos << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Check if position in list is correct
- if ((((page->header.freeArea - 128) / 512) != page->header.pageArrayPos) ||
- (page->header.pageArrayPos != tipaArrayPos)) {
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " Incorrect position in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " tipaArrayPos = " << tipaArrayPos << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Check if page is already in list.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- if (pagePtr.i == pageId) {
- jam();
- ndbout << "ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << "Page exists already in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl;
- printoutInfoAndShutdown(page);
- }
- pagePtr.i = page->header.nextPage;
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-}//Dbacc::checkPageB4Insert()
-
-// --------------------------------------------------------------------------------- */
-// Check the page to remove from the pageArrayList.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Remove(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- Uint32 noOfOccurrence = 0;
- Uint32 noOfPagesInList = 0;
- LongKeyPage *page;
-
- LongKeyPage *prevPage;
- LongKeyPage *nextPage;
- Page8Ptr rfpPrevPageptr;
- Page8Ptr rfpNextPageptr;
-
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- // Check that page is in list.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- noOfPagesInList++;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- if (pagePtr.i == pageId) {
- // Check the consistent in list.
- if (page->header.prevPage != RNIL) {
- rfpPrevPageptr.i = page->header.prevPage;
- ptrCheckGuard(rfpPrevPageptr, cpagesize, page8);
- prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0];
- if (prevPage->header.nextPage != pageId) {
- ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl
- << "prevPage->header.nextPage = " << prevPage->header.nextPage << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
- }
- // Check the consistent in list.
- if (page->header.nextPage != RNIL) {
- rfpNextPageptr.i = page->header.nextPage;
- ptrCheckGuard(rfpNextPageptr, cpagesize, page8);
- nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0];
- if (nextPage->header.prevPage != pageId) {
- ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl
- << "nextPage->header.prevPage = " << nextPage->header.prevPage << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
- }
- jam();
- noOfOccurrence++;
- }
- pagePtr.i = page->header.nextPage;
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-
- if (noOfOccurrence != 1) {
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- ndbout << "ERROR in checkPageB4Remove, called from " << calledFrom << endl
- << "Page occur " << noOfOccurrence << " times in list" << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
-}//Dbacc::checkPageB4Remove()
-
-
-// --------------------------------------------------------------------------------- */
-// Printout an error message and shutdown node.
-// --------------------------------------------------------------------------------- */
-void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) {
- ndbout << " page->header.pageArrayPos = " << page->header.pageArrayPos << endl
- << " ((page->header.freeArea - 128) / 512) = "
- << ((page->header.freeArea - 128) / 512) << endl
- << " page->header.freeArea = " << page->header.freeArea << endl
- << " page->header.noOfElements = " << page->header.noOfElements << endl
- << " page->header.nextPage = " << page->header.nextPage << endl
- << " page->header.prevPage = " << page->header.prevPage << endl
- << " page->header.nextFreeIndex = " << page->header.nextFreeIndex << endl
- << " page->header.insertPos = " << page->header.insertPos << endl
- << " page->header.highestIndex = " << page->header.highestIndex << endl
- << " page->header.pageId = " << page->header.pageId << endl;
- ndbrequire(false);
-}//Dbacc::printoutInfoAndShutdown()
-
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
@@ -4419,7 +3186,7 @@ void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) {
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* */
-/* MODULE: READ */
+/* MODULE: GET_ELEMENT */
/* THE FOLLOWING SUBROUTINES ARE ONLY USED BY GET_ELEMENT AND */
/* GETDIRINDEX. THIS ROUTINE IS THE SOLE INTERFACE TO GET ELEMENTS */
/* FROM THE INDEX. CURRENT USERS ARE ALL REQUESTS AND EXECUTE UNDO LOG */
@@ -4480,6 +3247,21 @@ void Dbacc::getdirindex(Signal* signal)
ptrCheckGuard(gdiPageptr, cpagesize, page8);
}//Dbacc::getdirindex()
+Uint32
+Dbacc::readTablePk(Uint32 localkey1)
+{
+ Uint32 tableId = fragrecptr.p->myTableId;
+ Uint32 fragId = fragrecptr.p->myfid;
+ Uint32 fragPageId = localkey1 >> MAX_TUPLES_BITS;
+ Uint32 pageIndex = localkey1 & ((1 << MAX_TUPLES_BITS ) - 1);
+#ifdef VM_TRACE
+ memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2);
+#endif
+ int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, ckeys, true);
+ ndbrequire(ret > 0);
+ return ret;
+}
+
/* --------------------------------------------------------------------------------- */
/* GET_ELEMENT */
/* INPUT: */
@@ -4521,7 +3303,6 @@ void Dbacc::getElement(Signal* signal)
Uint32 tgeNextptrtype;
register Uint32 tgeKeyptr;
register Uint32 tgeRemLen;
- register Uint32 tgeCompareLen;
register Uint32 TelemLen = fragrecptr.p->elementLength;
register Uint32* Tkeydata = (Uint32*)&signal->theData[7];
@@ -4529,20 +3310,15 @@ void Dbacc::getElement(Signal* signal)
tgePageindex = tgdiPageindex;
gePageptr = gdiPageptr;
tgeResult = ZFALSE;
- tgeCompareLen = fragrecptr.p->keyLength;
- const Uint32 isAccLockReq = operationRecPtr.p->isAccLockReq;
- if (isAccLockReq) {
- jam();
- tgeCompareLen = 0;
- }
+ /*
+ * The value seached is
+ * - table key for ACCKEYREQ, stored in TUP
+ * - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
+ */
+ const bool searchLocalKey =
+ operationRecPtr.p->isAccLockReq || operationRecPtr.p->isUndoLogReq;
- // We can handle keylength up to 8, but not more (0 means dynamic)
- if (tgeCompareLen >= 9) {
- ACCKEY_error(2); return;
- }//if
- if (TelemLen < 3) {
- ACCKEY_error(3); return;
- }//if
+ ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
tgeNextptrtype = ZLEFT;
tgeLocked = 0;
@@ -4573,7 +3349,7 @@ void Dbacc::getElement(Signal* signal)
} else {
ACCKEY_error(6); return;
}//if
- if (tgeRemLen >= TelemLen) {
+ if (tgeRemLen >= ZCON_HEAD_SIZE + TelemLen) {
if (tgeRemLen > ZBUF_SIZE) {
ACCKEY_error(7); return;
}//if
@@ -4581,151 +3357,46 @@ void Dbacc::getElement(Signal* signal)
// There is at least one element in this container. Check if it is the element
// searched for.
/* --------------------------------------------------------------------------------- */
- if (tgeCompareLen != 0) {
- /* --------------------------------------------------------------------------------- */
- /* THIS PART IS USED TO SEARCH FOR KEYS WITH FIXED SIZE. THE LOOP TAKES CARE */
- /* OF SEARCHING THROUGH ALL ELEMENTS IN ONE CONTAINER. */
- /* --------------------------------------------------------------------------------- */
- do {
- register Uint32 TdataIndex = 0;
- register Uint32 TgeIndex = 0;
+ do {
+ tgeElementHeader = gePageptr.p->word32[tgeElementptr];
+ tgeRemLen = tgeRemLen - TelemLen;
+ Uint32 hashValuePart;
+ if (ElementHeader::getLocked(tgeElementHeader)) {
jam();
- tgeRemLen = tgeRemLen - TelemLen;
- do {
- if (gePageptr.p->word32[tgeKeyptr + TgeIndex] != Tkeydata[TdataIndex]) {
- goto compare_next;
- }//if
- TdataIndex++;
- TgeIndex += tgeForward;
- } while (TdataIndex < tgeCompareLen);
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */
- /* --------------------------------------------------------------------------------- */
+ geTmpOperationRecPtr.i = ElementHeader::getOpPtrI(tgeElementHeader);
+ ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec);
+ hashValuePart = geTmpOperationRecPtr.p->hashvaluePart;
+ } else {
jam();
-#if __ia64 == 1
-#if __INTEL_COMPILER == 810
- // prevents SIGSEGV under icc -O1
- ndb_acc_ia64_icc810_dummy_func();
-#endif
-#endif
- tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]);
- tgeResult = ZTRUE;
- TdataIndex = tgeElementptr + tgeForward;
- TgeIndex = TdataIndex + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex];
- return;
- /* --------------------------------------------------------------------------------- */
- /* COMPARE NEXT ELEMENT */
- /* --------------------------------------------------------------------------------- */
- compare_next:
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeKeyptr = tgeKeyptr + tgeElemStep;
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- } else if (! isAccLockReq) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS PART IS USED TO SEARCH FOR KEYS WITH VARIABLE LENGTH OR FIXED LENGTH */
- /* GREATER THAN 32 BYTES. IN THIS CASE THE KEY PART IS STORED IN A SPECIAL */
- /* LONG PAGE PART AND THE HASH INDEX CONTAINS A REFERENCE TO THERE PLUS A */
- /* PART OF THE HASH VALUE. */
- /* --------------------------------------------------------------------------------- */
- do {
- tgeElementHeader = gePageptr.p->word32[tgeElementptr];
- tgeRemLen = tgeRemLen - TelemLen;
- Uint32 hashValuePart;
- if (ElementHeader::getLocked(tgeElementHeader)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IN THIS CASE THE HASH VALUE PART OF THE ELEMENT HEADER IS STORED IN THE */
- /* OPERATION THAT OWNS THE LOCK. IN THIS CASE WE MIGHT AS WELL GO AHEAD AND */
- /* CHECK THE KEY IN THE LONG PAGE. */
- /* --------------------------------------------------------------------------------- */
- geTmpOperationRecPtr.i =
- ElementHeader::getOpPtrI(tgeElementHeader);
- ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec);
- hashValuePart = geTmpOperationRecPtr.p->hashvaluePart;
+ hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
+ }
+ if (hashValuePart == opHashValuePart) {
+ jam();
+ Uint32 localkey1 = gePageptr.p->word32[tgeElementptr + tgeForward];
+ Uint32 localkey2 = 0;
+ bool found;
+ if (! searchLocalKey) {
+ Uint32 len = readTablePk(localkey1);
+ found = (len == operationRecPtr.p->xfrmtupkeylen) &&
+ (memcmp(Tkeydata, ckeys, len << 2) == 0);
} else {
jam();
- /* --------------------------------------------------------------------------------- */
- /* IN THIS CASE THE HASH VALUE PART CAN BE CHECKED TO SEE IF THE HASH VALUE */
- /* GIVES US A REASON TO CONTINUE CHECKING THE FULL KEY. */
- /* --------------------------------------------------------------------------------- */
- hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
- }//if
-
- if (hashValuePart == opHashValuePart) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IF THE HASH VALUES ARE EQUAL THEN XOR-ING THEM WILL GIVE THE RESULT 0. */
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND A KEY WITH IDENTICAL HASH VALUE. MOST LIKELY WE HAVE FOUND THE*/
- /* ELEMENT BUT FIRST WE NEED TO PERFORM A KEY COMPARISON. */
- /* --------------------------------------------------------------------------------- */
- tslcPageIndex = gePageptr.p->word32[tgeKeyptr] & 0x3ff;
- tslcPagedir = gePageptr.p->word32[tgeKeyptr] >> 10;
- searchLongKey(signal, true);
- if (tslcResult == ZTRUE) {
- register Uint32 TlocData1, TlocData2;
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */
- /* --------------------------------------------------------------------------------- */
- tgeLocked = ElementHeader::getLocked(tgeElementHeader);
- tgeResult = ZTRUE;
- TlocData1 = tgeElementptr + tgeForward;
- TlocData2 = TlocData1 + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TlocData1];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TlocData2];
- return;
- }//if
+ found = (localkey1 == Tkeydata[0]);
}
- /* --------------------------------------------------------------------------------- */
- /* COMPARE NEXT ELEMENT */
- /* --------------------------------------------------------------------------------- */
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeKeyptr = tgeKeyptr + tgeElemStep;
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* Search for local key in a lock request */
- /* --------------------------------------------------------------------------------- */
- do {
- tgeRemLen = tgeRemLen - TelemLen;
- // position of local key word 1
- Uint32 TdataIndex = tgeElementptr + tgeForward;
- // XXX assume localkeylen is 1
- if (gePageptr.p->word32[TdataIndex] == Tkeydata[0]) {
+ if (found) {
jam();
- tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]);
+ tgeLocked = ElementHeader::getLocked(tgeElementHeader);
tgeResult = ZTRUE;
- // position of local key word 2
- Uint32 TgeIndex = TdataIndex + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex];
-
- if (fragrecptr.p->keyLength == 0) {
- // set up long key variables in operation record
- tslcPageIndex = gePageptr.p->word32[tgeKeyptr] & 0x3ff;
- tslcPagedir = gePageptr.p->word32[tgeKeyptr] >> 10;
- // no verification since we have no key data
- searchLongKey(signal, false);
- }
+ operationRecPtr.p->localdata[0] = localkey1;
+ operationRecPtr.p->localdata[1] = localkey2;
return;
- }//if
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- }//if
+ }
+ }
+ if (tgeRemLen <= ZCON_HEAD_SIZE) {
+ break;
+ }
+ tgeElementptr = tgeElementptr + tgeElemStep;
+ } while (true);
}//if
if (tgeRemLen != ZCON_HEAD_SIZE) {
ACCKEY_error(8); return;
@@ -4756,71 +3427,6 @@ void Dbacc::getElement(Signal* signal)
}//Dbacc::getElement()
/* --------------------------------------------------------------------------------- */
-/* SEARCH_LONG_KEY */
-/* INPUT: */
-/* TSLC_PAGEDIR PAGE DIRECTORY OF LONG PAGE */
-/* TSLC_PAGE_INDEX PAGE INDEX IN LONG PAGE */
-/* GE_OPERATION_REC_PTR */
-/* OUTPUT: */
-/* TSLC_RESULT */
-/* DESCRIPTION: SEARCH FOR AN ELEMENT IN A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::searchLongKey(Signal* signal, bool verify)
-{
- DirRangePtr slcOverflowrangeptr;
- DirectoryarrayPtr slcOverflowDirptr;
- Page8Ptr slcPageptr;
- Uint32 tslcIndexValue;
- Uint32 tslcStartIndex;
- Uint32 tslcIndex;
- Uint32 guard30;
- Uint32* Tkeydata = (Uint32*)&signal->theData[7];
-
-
- slcOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(slcOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tslcPagedir >> 8), 256);
- slcOverflowDirptr.i = slcOverflowrangeptr.p->dirArray[tslcPagedir >> 8];
- ptrCheckGuard(slcOverflowDirptr, cdirarraysize, directoryarray);
-
- // dbgWord32(slcOverflowDirptr, (int) (tslcPagedir & 0xff), slcOverflowDirptr.p->pagep[tslcPagedir & 0xff]);
-
- slcPageptr.i = slcOverflowDirptr.p->pagep[tslcPagedir & 0xff];
- ptrCheckGuard(slcPageptr, cpagesize, page8);
- arrGuard(ZWORDS_IN_PAGE - tslcPageIndex, 2048);
- dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, (int)slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] & 0xffff);
- dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] >> 16);
- tslcIndexValue = slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex];
- if (verify) {
- if ((tslcIndexValue >> 16) != operationRecPtr.p->tupkeylen) {
- jam();
- tslcResult = ZFALSE;
- return;
- }//if
- }
- tslcStartIndex = tslcIndexValue & 0xffff;
- guard30 = operationRecPtr.p->tupkeylen - 1;
- arrGuard(guard30, 2048);
- arrGuard(guard30 + tslcStartIndex, 2048);
- if (verify) {
- for (tslcIndex = 0; tslcIndex <= guard30; tslcIndex++) {
- dbgWord32(slcPageptr, tslcIndex + tslcStartIndex, slcPageptr.p->word32[tslcIndex + tslcStartIndex]);
- if (slcPageptr.p->word32[tslcIndex + tslcStartIndex] != Tkeydata[tslcIndex]) {
- jam();
- tslcResult = ZFALSE;
- return;
- }//if
- }//for
- }
- jam();
- tslcResult = ZTRUE;
- operationRecPtr.p->longPagePtr = slcPageptr.i;
- operationRecPtr.p->longKeyPageIndex = tslcPageIndex;
- arrGuard(tslcPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
- arrGuard(slcPageptr.i, cpagesize);
-}//Dbacc::searchLongKey()
-
-/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* */
@@ -4863,13 +3469,6 @@ void Dbacc::commitdelete(Signal* signal, bool systemRestart)
EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 4);
jamEntry();
}//if
- if (fragrecptr.p->keyLength == 0) {
- jam();
- tdlkLogicalPageIndex = operationRecPtr.p->longKeyPageIndex;
- dlkPageptr.i = operationRecPtr.p->longPagePtr;
- ptrCheckGuard(dlkPageptr, cpagesize, page8);
- deleteLongKey(signal);
- }//if
getdirindex(signal);
tlastPageindex = tgdiPageindex;
lastPageptr.i = gdiPageptr.i;
@@ -5428,50 +4027,6 @@ void Dbacc::checkoverfreelist(Signal* signal)
}//if
}//Dbacc::checkoverfreelist()
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_LONG_PAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseLongPage(Signal* signal)
-{
- DirRangePtr rlpOverflowrangeptr;
- DirectoryarrayPtr rlpOverflowDirptr;
- Uint32 trlpTmp1;
- Uint32 trlpTmp2;
- Uint32 trlpTmp3;
-
- jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = rlopPageptr.p->word32[ZPOS_PAGE_ID];
- sorOverflowRecPtr.p->overpage = RNIL;
- priOverflowRecPtr = sorOverflowRecPtr;
- putRecInFreeOverdir(signal);
- trlpTmp1 = sorOverflowRecPtr.p->dirindex;
- rlpOverflowrangeptr.i = fragrecptr.p->overflowdir;
- trlpTmp2 = trlpTmp1 >> 8;
- trlpTmp3 = trlpTmp1 & 0xff;
- ptrCheckGuard(rlpOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard(trlpTmp2, 256);
- rlpOverflowDirptr.i = rlpOverflowrangeptr.p->dirArray[trlpTmp2];
- ptrCheckGuard(rlpOverflowDirptr, cdirarraysize, directoryarray);
- rlpOverflowDirptr.p->pagep[trlpTmp3] = RNIL;
-
- if (cundoLogActive != ZTRUE) {
- // Remove from page array.
- trfpArrayPos = rlopPageptr.p->word32[ZPOS_ARRAY_POS];
- rfpPageptr = rlopPageptr;
- removeFromPageArrayList(signal);
- }
-
- // Reset page header
- iloPageptr = rlopPageptr;
- tiloIndex = rlopPageptr.p->word32[ZPOS_PAGE_ID];
- initLongOverpage(signal);
-
- rpPageptr = rlopPageptr;
- releasePage(signal);
-}//Dbacc::releaseLongPage()
-
-
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
@@ -6162,16 +4717,16 @@ Uint32 Dbacc::executeNextOperation(Signal* signal)
else if(operationRecPtr.p->operation == ZWRITE)
{
jam();
- operationRecPtr.p->operation = ZINSERT;
+ operationRecPtr.p->operation = ZUPDATE;
if (operationRecPtr.p->prevParallelQue != RNIL) {
OperationrecPtr prevOpPtr;
jam();
prevOpPtr.i = operationRecPtr.p->prevParallelQue;
ptrCheckGuard(prevOpPtr, coprecsize, operationrec);
- if (prevOpPtr.p->operation != ZDELETE)
+ if (prevOpPtr.p->operation == ZDELETE)
{
jam();
- operationRecPtr.p->operation = ZUPDATE;
+ operationRecPtr.p->operation = ZINSERT;
}
}
}
@@ -6761,8 +5316,7 @@ void Dbacc::execDEBUG_SIG(Signal* signal)
jamEntry();
expPageptr.i = signal->theData[0];
- progError(__LINE__,
- ERR_SR_UNDOLOG);
+ progError(__LINE__, NDBD_EXIT_SR_UNDOLOG);
return;
}//Dbacc::execDEBUG_SIG()
@@ -6779,14 +5333,8 @@ void Dbacc::expandcontainer(Signal* signal)
Uint32 texcHashvalue;
Uint32 texcTmp;
Uint32 texcIndex;
- Uint32 texpKeyLen;
Uint32 guard20;
- texpKeyLen = fragrecptr.p->keyLength;
- if (texpKeyLen == 0) {
- jam();
- texpKeyLen = ZACTIVE_LONG_KEY_LEN;
- }//if
cexcPrevpageptr = RNIL;
cexcPrevconptr = 0;
cexcForward = ZTRUE;
@@ -6873,18 +5421,10 @@ void Dbacc::expandcontainer(Signal* signal)
clocalkey[texcIndex] = excPageptr.p->word32[texcTmp];
texcTmp = texcTmp + cexcForward;
}//for
- guard20 = texpKeyLen - 1;
- for (texcIndex = 0; texcIndex <= guard20; texcIndex++) {
- arrGuard(texcIndex, 2048);
- arrGuard(texcTmp, 2048);
- ckeys[texcIndex] = excPageptr.p->word32[texcTmp];
- texcTmp = texcTmp + cexcForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = texpKeyLen;
insertElement(signal);
fragrecptr.p->expReceiveIndex = tidrPageindex;
fragrecptr.p->expReceivePageptr = idrPageptr.i;
@@ -6966,17 +5506,10 @@ void Dbacc::expandcontainer(Signal* signal)
clocalkey[texcIndex] = lastPageptr.p->word32[texcTmp];
texcTmp = texcTmp + tlastForward;
}//for
- for (texcIndex = 0; texcIndex < texpKeyLen; texcIndex++) {
- arrGuard(texcIndex, 2048);
- arrGuard(texcTmp, 2048);
- ckeys[texcIndex] = lastPageptr.p->word32[texcTmp];
- texcTmp = texcTmp + tlastForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = texpKeyLen;
insertElement(signal);
fragrecptr.p->expReceiveIndex = tidrPageindex;
fragrecptr.p->expReceivePageptr = idrPageptr.i;
@@ -7096,7 +5629,7 @@ Uint32 Dbacc::checkScanShrink(Signal* signal)
//-------------------------------------------------------------
} else {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
return TreturnCode;
}//if
}//if
@@ -7457,18 +5990,12 @@ void Dbacc::shrinkcontainer(Signal* signal)
Uint32 tshrElementptr;
Uint32 tshrRemLen;
Uint32 tshrInc;
- Uint32 tshrKeyLen;
Uint32 tshrTmp;
Uint32 tshrIndex;
Uint32 guard21;
tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE;
- tshrKeyLen = fragrecptr.p->keyLength;
- if (tshrKeyLen == 0) {
- jam();
- tshrKeyLen = ZACTIVE_LONG_KEY_LEN;
- }//if
- tshrInc = (ZELEM_HEAD_SIZE + tshrKeyLen) + fragrecptr.p->localkeylen;
+ tshrInc = fragrecptr.p->elementLength;
if (cexcForward == ZTRUE) {
jam();
tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
@@ -7517,18 +6044,10 @@ void Dbacc::shrinkcontainer(Signal* signal)
clocalkey[tshrIndex] = excPageptr.p->word32[tshrTmp];
tshrTmp = tshrTmp + cexcForward;
}//for
- guard21 = tshrKeyLen - 1;
- for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) {
- arrGuard(tshrIndex, 2048);
- arrGuard(tshrTmp, 2048);
- ckeys[tshrIndex] = excPageptr.p->word32[tshrTmp];
- tshrTmp = tshrTmp + cexcForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = tshrKeyLen;
insertElement(signal);
/* --------------------------------------------------------------------------------- */
/* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */
@@ -7538,7 +6057,7 @@ void Dbacc::shrinkcontainer(Signal* signal)
fragrecptr.p->expReceiveForward = tidrForward;
if (tshrRemLen < tshrInc) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}//if
tshrRemLen = tshrRemLen - tshrInc;
if (tshrRemLen != 0) {
@@ -7573,7 +6092,7 @@ void Dbacc::nextcontainerinfoExp(Signal* signal)
cexcForward = cminusOne;
} else {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
cexcForward = 0; /* DUMMY FOR COMPILER */
}//if
if (tnciNextSamePage == ZFALSE) {
@@ -8072,7 +6591,7 @@ void Dbacc::execACC_SAVE_PAGES(Signal* signal)
ptrCheckGuard(lcpConnectptr, clcpConnectsize, lcpConnectrec);
if (lcpConnectptr.p->lcpstate != LCP_ACTIVE) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
return;
}//if
if (ERROR_INSERTED(3000)) {
@@ -8256,17 +6775,9 @@ void Dbacc::saveOverPagesLab(Signal* signal)
jam();
ropPageptr = sopPageptr;
releaseOverpage(signal);
- } else if (((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) ==
- ZLONG_PAGE_TYPE) {
- //----------------------------------------------------------------------
- // The long key page is empty, release it.
- //----------------------------------------------------------------------
- jam();
- rlopPageptr = sopPageptr;
- releaseLongPage(signal);
} else {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}
}//if
}
@@ -8406,7 +6917,7 @@ void Dbacc::checkSyncUndoPagesLab(Signal* signal)
break;
default:
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
return;
break;
}//switch
@@ -8655,66 +7166,63 @@ void Dbacc::lcpCopyPage(Signal* signal)
}//for
}//for
tlcnChecksum = Tchs;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) {
- jam();
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- lcpUpdatePage(signal);
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
+ if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
+ jam();
/*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
+ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
+ /* HEADER OF 2 WORDS. */
/*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlcnConIndex = ZHEAD_SIZE;
+ tlupForward = 1;
+ for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
tlupIndex = tlcnConIndex;
tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
- lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal);
- return;
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal);
- return;
- }//if
+ tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
+ }//for
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
+ tlupForward = 1;
+ lcpUpdatePage(signal);
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ sendSystemerror(signal, __LINE__);
+ return;
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlupForward = cminusOne;
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex - 1;
+ lcpUpdatePage(signal);
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ sendSystemerror(signal, __LINE__);
+ return;
}//if
lcnCopyPageptr.p->word32[ZPOS_CHECKSUM] = tlcnChecksum;
}//Dbacc::lcpCopyPage()
@@ -8760,7 +7268,7 @@ void Dbacc::lcpUpdatePage(Signal* signal)
}//while
if (tlupConLen < ZCON_HEAD_SIZE) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}//if
}//Dbacc::lcpUpdatePage()
@@ -8775,78 +7283,75 @@ void Dbacc::srCheckPage(Signal* signal)
Uint32 tlcnIndex;
lupPageptr.p = lcnCopyPageptr.p;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) {
- jam();
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
+ if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
+ jam();
/*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
+ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
+ /* HEADER OF 2 WORDS. */
/*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlcnConIndex = ZHEAD_SIZE;
+ tlupForward = 1;
+ for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
tlupIndex = tlcnConIndex;
tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
srCheckContainer(signal);
if (tresult != 0) {
jam();
return;
}//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
+ tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
+ }//for
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
+ tlupForward = 1;
+ srCheckContainer(signal);
+ if (tresult != 0) {
jam();
- tresult = 4;
return;
}//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ tresult = 4;
+ return;
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlupForward = cminusOne;
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex - 1;
+ srCheckContainer(signal);
+ if (tresult != 0) {
jam();
- tresult = 4;
return;
}//if
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ tresult = 4;
+ return;
}//if
}//Dbacc::srCheckPage()
@@ -9030,50 +7535,14 @@ void Dbacc::undoWritingProcess(Signal* signal)
writeUndoDataInfo(signal);
checkUndoPages(signal);
}//if
- } else if (tpageType != ZLONG_PAGE_TYPE) {
+ } else {
jam();
/* --------------------------------------------------------------------------- */
/* ONLY PAGE INFO AND OVERFLOW PAGE INFO CAN BE LOGGED BY THIS ROUTINE. A */
/* SERIOUS ERROR. */
/* --------------------------------------------------------------------------- */
- sendSystemerror(signal);
- } else {
- /* --------------------------------------------------------------------------------- */
- /* THIS LOG RECORD IS GENERATED ON A LONG KEY PAGE. THESE PAGES USE LOGICAL */
- /* LOGGING. */
- /* --------------------------------------------------------------------------------- */
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */
- /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/
- /* NOT EXIST AT START OF LCP. */
- /* --------------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN INSERT OR UNDO */
- /* OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG THE KEY TO BE REINSERTED WHILE */
- /* UNDO OF INSERT ONLY NEEDS TO LOG THE INDEX TO BE DELETED. */
- /* --------------------------------------------------------------------------------- */
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- if (cundoinfolength == 0) {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY);
- } else {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY);
- arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048);
- tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff;
- writeUndoDataInfo(signal);
- }//if
- checkUndoPages(signal);
- }//if
- }//if
+ sendSystemerror(signal, __LINE__);
+ }
} else {
if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) {
jam();
@@ -9108,46 +7577,7 @@ void Dbacc::undoWritingProcess(Signal* signal)
checkUndoPages(signal);
}//if
}//if
- } else if (tpageType == ZLONG_PAGE_TYPE) {
- if (tactivePageDir < fragrecptr.p->lcpDirIndex) {
- jam();
- // -------------------------------------------------------------
- // THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT.
- // -------------------------------------------------------------
- } else {
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- // -------------------------------------------------------------
- // OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW
- // PAGES SINCE THE START OF THE LOCAL CHECKPOINT. WE NEED NOT
- // LOG ANY UPDATES OF PAGES THAT DID NOT EXIST AT START OF LCP.
- // -------------------------------------------------------------
- } else {
- jam();
- // -------------------------------------------------------------
- // LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN
- // INSERT OR UNDO OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG
- // THE KEY TO BE REINSERTED WHILE UNDO OF INSERT ONLY NEEDS TO
- // LOG THE INDEX TO BE DELETED.
- // -------------------------------------------------------------
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- if (cundoinfolength == 0) {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY);
- } else {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY);
- arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048);
- tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff;
- writeUndoDataInfo(signal);
- }//if
- checkUndoPages(signal);
- }//if
- }//if
- }//if
+ }
}//if
}//if
}//Dbacc::undoWritingProcess()
@@ -9200,8 +7630,9 @@ void Dbacc::writeUndoHeader(Signal* signal,
(UndoHeader *) &undopageptr.p->undoword[theadundoindex];
undoHeaderPtr->tableId = rootfragrecptr.p->mytabptr;
- undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0];
+ undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0] >> 1;
undoHeaderPtr->localFragId = fragrecptr.p->myfid;
+ ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
Uint32 Ttmp = cundoinfolength;
Ttmp = (Ttmp << 4) + pageType;
Ttmp = Ttmp << 14;
@@ -9231,52 +7662,16 @@ void Dbacc::writeUndoOpInfo(Signal* signal)
undopageptr.p->undoword[tundoindex + 1] = operationRecPtr.p->hashValue;
undopageptr.p->undoword[tundoindex + 2] = operationRecPtr.p->tupkeylen;
tundoindex = tundoindex + 3;
- if (fragrecptr.p->keyLength != 0) {
- // Fixed size keys
- jam();
- locPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(locPageptr, cpagesize, page8);
- Uint32 Tforward = operationRecPtr.p->elementIsforward;
- Uint32 TelemPtr = operationRecPtr.p->elementPointer;
- TelemPtr += Tforward;
- TelemPtr += Tforward;
- //---------------------------------------------------------------------------------
- // Now the pointer is at the start of the key part of the element. Now copy from there
- // to the UNDO log.
- //---------------------------------------------------------------------------------
- Uint32 keyLen = operationRecPtr.p->tupkeylen;
- ndbrequire(keyLen <= 8);
- arrGuard(tundoindex+keyLen, 8192);
- for (Uint32 twuoiIndex = 0; twuoiIndex < keyLen; twuoiIndex++) {
- jam();
- arrGuard(TelemPtr, 2048);
- undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
- tundoindex++;
- TelemPtr += Tforward;
- }//for
- cundoinfolength = ZOP_HEAD_INFO_LN + operationRecPtr.p->tupkeylen;
- } else {
- // Long keys
- jam();
-
- arrGuard(operationRecPtr.p->longKeyPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
- locPageptr.i = operationRecPtr.p->longPagePtr;
- ptrCheckGuard(locPageptr, cpagesize, page8);
-
- Uint32 indexValue =
- locPageptr.p->word32[ZWORDS_IN_PAGE - operationRecPtr.p->longKeyPageIndex];
- Uint32 keyLen = indexValue >> 16;
- Uint32 physPageIndex = indexValue & 0xffff;
- ndbrequire(keyLen == operationRecPtr.p->tupkeylen);
-
- arrGuard(tundoindex+keyLen, 8192);
- arrGuard(physPageIndex+keyLen, 2048);
- for (Uint32 i = 0; i < keyLen; i++){
- undopageptr.p->undoword[tundoindex + i] = locPageptr.p->word32[physPageIndex+i];
- }
- tundoindex = tundoindex + keyLen;
- cundoinfolength = ZOP_HEAD_INFO_LN + keyLen;
- }//if
+ // log localkey1
+ locPageptr.i = operationRecPtr.p->elementPage;
+ ptrCheckGuard(locPageptr, cpagesize, page8);
+ Uint32 Tforward = operationRecPtr.p->elementIsforward;
+ Uint32 TelemPtr = operationRecPtr.p->elementPointer;
+ TelemPtr += Tforward; // ZELEM_HEAD_SIZE
+ arrGuard(tundoindex+1, 8192);
+ undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
+ tundoindex++;
+ cundoinfolength = ZOP_HEAD_INFO_LN + 1;
}//Dbacc::writeUndoOpInfo()
/* --------------------------------------------------------------------------------- */
@@ -9460,7 +7855,7 @@ void Dbacc::initFragAdd(Signal* signal,
}//if
regFragPtr.p->fragState = ACTIVEFRAG;
// NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
- regFragPtr.p->myfid = (rootFragIndex << (lhFragBits - 1)) | req->fragId;
+ regFragPtr.p->myfid = (req->fragId << 1) | rootFragIndex;
regFragPtr.p->myroot = rootIndex;
regFragPtr.p->myTableId = req->tableId;
ndbrequire(req->kValue == 6);
@@ -9488,17 +7883,16 @@ void Dbacc::initFragAdd(Signal* signal,
regFragPtr.p->dirsize = 1;
regFragPtr.p->loadingFlag = ZFALSE;
regFragPtr.p->keyLength = req->keyLength;
- if (req->keyLength == 0) {
- jam();
- regFragPtr.p->elementLength = (1 + ZELEM_HEAD_SIZE) + regFragPtr.p->localkeylen;
- } else {
- jam();
- regFragPtr.p->elementLength = (ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen) + regFragPtr.p->keyLength;
- }//if
+ ndbrequire(req->keyLength != 0);
+ regFragPtr.p->elementLength = ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen;
Uint32 Tmp1 = (regFragPtr.p->maxp + 1) + regFragPtr.p->p;
Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor;
Tmp2 = Tmp1 * Tmp2;
regFragPtr.p->slackCheck = Tmp2;
+
+ Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr;
+ regFragPtr.p->hasCharAttr = hasCharAttr;
+
}//Dbacc::initFragAdd()
void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
@@ -9518,6 +7912,7 @@ void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
regFragPtr.p->activeDataPage = 0;
regFragPtr.p->createLcp = ZFALSE;
regFragPtr.p->stopQueOp = ZFALSE;
+ regFragPtr.p->hasCharAttr = ZFALSE;
regFragPtr.p->nextAllocPage = 0;
regFragPtr.p->nrWaitWriteUndoExit = 0;
regFragPtr.p->lastUndoIsStored = ZFALSE;
@@ -9776,7 +8171,7 @@ void Dbacc::srReadPagesLab(Signal* signal)
for (Uint32 i = 0; i < limitLoop; i++) {
jam();
seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
+ ndbrequireErr(tresult <= ZLIMIT_OF_ERROR, NDBD_EXIT_SR_OUT_OF_INDEXMEMORY);
fragrecptr.p->datapages[i] = spPageptr.i;
signal->theData[i + 6] = spPageptr.i;
}//for
@@ -10103,7 +8498,7 @@ void Dbacc::startUndoLab(Signal* signal)
}//for
// Send report of how many undo log records where executed
- signal->theData[0] = EventReport::UNDORecordsExecuted;
+ signal->theData[0] = NDB_LE_UNDORecordsExecuted;
signal->theData[1] = DBACC; // From block
signal->theData[2] = 0; // Total records executed
for (int i = 0; i < 10; i++){
@@ -10149,7 +8544,7 @@ void Dbacc::startActiveUndo(Signal* signal)
/*---------------------------------------------------------------------------*/
if (cfsFirstfreeconnect == RNIL) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}//if
seizeFsConnectRec(signal);
cactiveSrFsPtr = fsConnectptr.i;
@@ -10296,6 +8691,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
// ROOT FRAGMENT ID
tfid = undoHeaderPtr->rootFragId;
+ ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
if (!getrootfragmentrec(signal, rootfragrecptr, tfid)) {
jam();
/*---------------------------------------------------------------------*/
@@ -10305,7 +8701,10 @@ void Dbacc::srDoUndoLab(Signal* signal)
creadyUndoaddress = cprevUndoaddress;
// PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS
cprevUndoaddress = undoHeaderPtr->prevUndoAddress;
- undoNext2Lab(signal);
+ undoNext2Lab(signal);
+#ifdef VM_TRACE
+ ndbout_c("ignoring root fid %d", (int)tfid);
+#endif
return;
}//if
/*-----------------------------------------------------------------------*/
@@ -10322,7 +8721,8 @@ void Dbacc::srDoUndoLab(Signal* signal)
ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
} else {
jam();
- progError(__LINE__, 0, "Invalid local fragment id in undo log");
+ progError(__LINE__, NDBD_EXIT_SR_UNDOLOG,
+ "Invalid local fragment id in undo log");
return;
}//if
}//if
@@ -10415,103 +8815,6 @@ void Dbacc::srDoUndoLab(Signal* signal)
break;
}
- case UndoHeader::ZUNDO_INSERT_LONG_KEY:{
- jam();
- /*---------------------------------------------------------------------*/
- /* WE WILL UNDO AN INSERT OF A LONG KEY. THIS IS PERFORMED BY DELETING */
- /* THE LONG KEY. */
- /*---------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- arrGuard(tmpP2, 256);
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- dlkPageptr.i = souDirptr.p->pagep[tmpP];
- ptrCheckGuard(dlkPageptr, cpagesize, page8);
- tdlkLogicalPageIndex = tundoPageindex;
- deleteLongKey(signal);
- break;
- }
-
- case UndoHeader::ZUNDO_DELETE_LONG_KEY: {
- jam();
- /*----------------------------------------------------------------------*/
- /* WE WILL UNDO DELETE OF A LONG KEY. THIS IS PERFORMED BY INSERTING */
- /* IT AGAIN. */
- /*----------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- taslpDirIndex = tmpP;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
-
- if(souDirptr.i == RNIL) {
- //----------------------------------------------------------------
- // Allocate a directory.
- //----------------------------------------------------------------
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }
- souDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- }
-
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- slkapPageptr.i = souDirptr.p->pagep[tmpP];
-
- if(slkapPageptr.i == RNIL) {
- //----------------------------------------------------------------
- // The delete operation was probably the last on the page and the
- // page was released and not written down to disk. We need to
- // allocate a page and put it in the same dirindex as it was in
- // before it was released.
- // This is because an eventual UNDO_INSERT on the same key in the
- // same LCP must be able to find the key and it has only the
- // dirindex to go on, the key itself is not saved on disk in a
- // UNDO_INSERT.
- //----------------------------------------------------------------
- jam();
- allocSpecificLongOverflowPage(signal);
- slkapPageptr.i = aslpPageptr.i;
- }
-
- ptrCheckGuard(slkapPageptr, cpagesize, page8);
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
-
- slkapCopyPageptr = spPageptr;
- ndbrequire(cundoinfolength <= 2048);
-
- for (Uint32 tmp = 0; tmp < cundoinfolength; tmp++) {
- dbgWord32(slkapCopyPageptr, tmp, undopageptr.p->undoword[tmpindex]);
- slkapCopyPageptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
- jam();
- //----------------------------------------------------------------
- // We must store the key at the same place it was deleted from.
- // This is because an eventual UNDO_INSERT on the same key in the
- // same LCP must be able to find the key and it has only the index
- // information stored on disk to go on, the key itself is not
- // saved on disk in an UNDO_INSERT.
- //----------------------------------------------------------------
- tslkapKeyLen = cundoinfolength;
- tslkapPageIndex = tundoPageindex;
- storeLongKeysAtPos(signal);
-
- rpPageptr = slkapCopyPageptr;
- releasePage(signal);
- break;
- }
-
case UndoHeader::ZOP_INFO: {
jam();
/*---------------------------------------------------------------------*/
@@ -10550,6 +8853,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
operationRecPtr.p->longKeyPageIndex = RNIL;
operationRecPtr.p->scanRecPtr = RNIL;
operationRecPtr.p->isAccLockReq = ZFALSE;
+ operationRecPtr.p->isUndoLogReq = ZTRUE;
// Read operation values from undo page
operationRecPtr.p->operation = undopageptr.p->undoword[tmpindex];
@@ -10559,17 +8863,15 @@ void Dbacc::srDoUndoLab(Signal* signal)
const Uint32 tkeylen = undopageptr.p->undoword[tmpindex];
tmpindex++;
operationRecPtr.p->tupkeylen = tkeylen;
+ operationRecPtr.p->xfrmtupkeylen = 0; // not used
operationRecPtr.p->fragptr = fragrecptr.i;
- ndbrequire((fragrecptr.p->keyLength == 0) ||
- ((fragrecptr.p->keyLength != 0) &&
- (fragrecptr.p->keyLength == tkeylen)));
+ ndbrequire(fragrecptr.p->keyLength != 0 &&
+ fragrecptr.p->keyLength == tkeylen);
- // Read keydata from undo page
- for (Uint32 tmp = 0; tmp < tkeylen; tmp++) {
- signal->theData[7+tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
+ // Read localkey1 from undo page
+ signal->theData[7 + 0] = undopageptr.p->undoword[tmpindex];
+ tmpindex = tmpindex + 1;
arrGuard((tmpindex - 1), 8192);
getElement(signal);
if (tgeResult != ZTRUE) {
@@ -10597,7 +8899,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
default:
jam();
- progError(__LINE__, 0, "Invalid pagetype in undo log");
+ progError(__LINE__, NDBD_EXIT_SR_UNDOLOG, "Invalid pagetype in undo log");
break;
}//switch(tpageType)
@@ -10752,43 +9054,25 @@ void Dbacc::execACC_OVER_REC(Signal* signal)
ptrCheckGuard(pnoPageidptr, cpagesize, page8);
tpnoPageType = pnoPageidptr.p->word32[ZPOS_PAGE_TYPE];
tpnoPageType = (tpnoPageType >> ZPOS_PAGE_TYPE_BIT) & 3;
- if (tpnoPageType == ZLONG_PAGE_TYPE) {
+ if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
jam();
- // This is to clean the list parameters.
- pnoPageidptr.p->word32[ZPOS_PREV_PAGE] = RNIL;
- pnoPageidptr.p->word32[ZPOS_NEXT_PAGE] = RNIL;
- if (pnoPageidptr.p->word32[ZPOS_ARRAY_POS] != 4) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* THE PAGE WAS A LONG PAGE AND IT BELONGED TO A FREE LIST. PUT IT INTO ONE */
- /* OF THE FREE LIST THEN. */
- /*---------------------------------------------------------------------------*/
- // Insert page!
- ipaPagePtr = pnoPageidptr;
- tipaArrayPos = pnoPageidptr.p->word32[ZPOS_ARRAY_POS];
- insertPageArrayList(signal);
- }//if
+ dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
+ pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
+ ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
} else {
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
- jam();
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
- } else {
+ jam();
+ seizeOverRec(signal);
+ sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
+ ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
+ dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
+ pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
+ sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
+ porOverflowRecPtr = sorOverflowRecPtr;
+ putOverflowRecInFrag(signal);
+ if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
- ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
- sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
- porOverflowRecPtr = sorOverflowRecPtr;
- putOverflowRecInFrag(signal);
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
- jam();
- ropPageptr = pnoPageidptr;
- releaseOverpage(signal);
- }//if
+ ropPageptr = pnoPageidptr;
+ releaseOverpage(signal);
}//if
}//if
}//if
@@ -10863,7 +9147,6 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
rootfragrecptr.p->scan[i] = scanPtr.i;
scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
- scanPtr.p->scanKeyinfoFlag = AccScanReq::getKeyinfoFlag(tscanFlag);
scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
/* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */
@@ -11086,7 +9369,7 @@ void Dbacc::checkNextBucketLab(Signal* signal)
/* --------------------------------------------------------------------------------- */
if (scanPtr.p->minBucketIndexToRescan != 0) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
return;
}//if
scanPtr.p->maxBucketIndexToRescan = fragrecptr.p->p + fragrecptr.p->maxp;
@@ -11251,7 +9534,7 @@ void Dbacc::checkNextFragmentLab(Signal* signal)
} else {
jam();
/* ALL ELEMENTS ARE SENT */
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}//if
}//if
/* --------------------------------------------------------------------------------- */
@@ -11611,11 +9894,6 @@ void Dbacc::initScanOpRec(Signal* signal)
Uint32 tisoTmp;
Uint32 tisoLocalPtr;
Uint32 guard24;
- Uint32 tisoPageIndex;
- Uint32 tisoPagedir;
- DirRangePtr tisoOverflowrangeptr;
- DirectoryarrayPtr tisoOverflowDirptr;
- Page8Ptr tisoPageptr;
scanPtr.p->scanOpsAllocated++;
@@ -11644,6 +9922,7 @@ void Dbacc::initScanOpRec(Signal* signal)
operationRecPtr.p->elementPointer = tisoElementptr;
operationRecPtr.p->elementPage = isoPageptr.i;
operationRecPtr.p->isAccLockReq = ZFALSE;
+ operationRecPtr.p->isUndoLogReq = ZFALSE;
tisoLocalPtr = tisoElementptr + tisoIsforward;
guard24 = fragrecptr.p->localkeylen - 1;
for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
@@ -11654,40 +9933,8 @@ void Dbacc::initScanOpRec(Signal* signal)
}//for
arrGuard(tisoLocalPtr, 2048);
operationRecPtr.p->keydata[0] = isoPageptr.p->word32[tisoLocalPtr];
- if (fragrecptr.p->keyLength != 0) {
- jam();
- operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
- guard24 = fragrecptr.p->keyLength - 1;
- for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
- arrGuard(tisoTmp, 8);
- arrGuard(tisoLocalPtr, 2048);
- operationRecPtr.p->keydata[tisoTmp] = isoPageptr.p->word32[tisoLocalPtr];
- tisoLocalPtr = tisoLocalPtr + tisoIsforward;
- }//for
- } else {
- // Long key handling. Put the long key reference in the operation records.
- tisoPageIndex = operationRecPtr.p->keydata[0] & 0x3ff;
- arrGuard(ZWORDS_IN_PAGE - tisoPageIndex, 2048);
-
- tisoPagedir = operationRecPtr.p->keydata[0] >> 10;
- arrGuard((tisoPagedir >> 8), 256);
-
- tisoOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(tisoOverflowrangeptr, cdirrangesize, dirRange);
-
- tisoOverflowDirptr.i = tisoOverflowrangeptr.p->dirArray[tisoPagedir >> 8];
- ptrCheckGuard(tisoOverflowDirptr, cdirarraysize, directoryarray);
-
- tisoPageptr.i = tisoOverflowDirptr.p->pagep[tisoPagedir & 0xff];
- ptrCheckGuard(tisoPageptr, cpagesize, page8);
-
- operationRecPtr.p->longPagePtr = tisoPageptr.i;
- operationRecPtr.p->longKeyPageIndex = tisoPageIndex;
-
- // Read length of key from page
- Uint32 tmp = tisoPageptr.p->word32[ZWORDS_IN_PAGE - tisoPageIndex];
- operationRecPtr.p->tupkeylen = tmp >> 16;
- }
+ operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
+ operationRecPtr.p->xfrmtupkeylen = 0; // not used
}//Dbacc::initScanOpRec()
/* --------------------------------------------------------------------------------- */
@@ -11882,21 +10129,15 @@ void Dbacc::releaseScanContainer(Signal* signal)
Uint32 trscElemlens;
Uint32 trscElemlen;
- if (trscContainerlen < 5) {
+ if (trscContainerlen < 4) {
if (trscContainerlen != ZCON_HEAD_SIZE) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}//if
- return; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */
- }//if
- trscElemlens = trscContainerlen - 2;
- if (fragrecptr.p->keyLength != 0) {
- jam();
- trscElemlen = (1 + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */
- } else {
- jam();
- trscElemlen = (1 + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */
+ return; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
}//if
+ trscElemlens = trscContainerlen - ZCON_HEAD_SIZE;
+ trscElemlen = fragrecptr.p->elementLength;
if (trscIsforward == 1) {
jam();
trscElementptr = trscContainerptr + ZCON_HEAD_SIZE;
@@ -11923,10 +10164,10 @@ void Dbacc::releaseScanContainer(Signal* signal)
}//if
trscElemlens = trscElemlens - trscElemlen;
trscElementptr = trscElementptr + trscElemStep;
- } while (trscElemlens > 2);
+ } while (trscElemlens > 1);
if (trscElemlens != 0) {
jam();
- sendSystemerror(signal);
+ sendSystemerror(signal, __LINE__);
}//if
}//Dbacc::releaseScanContainer()
@@ -11982,19 +10223,12 @@ bool Dbacc::searchScanContainer(Signal* signal)
Uint32 tsscElemlen;
Uint32 tsscElemStep;
- if (tsscContainerlen < 5) {
+ if (tsscContainerlen < 4) {
jam();
- return false; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */
+ return false; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
}//if
tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE;
- if (fragrecptr.p->keyLength == 0) {
- jam();
- tsscElemlen = (ZELEM_HEAD_SIZE + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen;
- } else {
- jam();
- /* LENGTH OF THE ELEMENT */
- tsscElemlen = (ZELEM_HEAD_SIZE + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen;
- }//if
+ tsscElemlen = fragrecptr.p->elementLength;
/* LENGTH OF THE ELEMENT */
if (tsscIsforward == 1) {
jam();
@@ -12032,7 +10266,7 @@ bool Dbacc::searchScanContainer(Signal* signal)
/* THE ELEMENT IS ALREADY SENT. */
/* SEARCH FOR NEXT ONE */
tsscElemlens = tsscElemlens - tsscElemlen;
- if (tsscElemlens > 2) {
+ if (tsscElemlens > 1) {
jam();
tsscElementptr = tsscElementptr + tsscElemStep;
goto SCANELEMENTLOOP001;
@@ -12047,172 +10281,20 @@ void Dbacc::sendNextScanConf(Signal* signal)
{
scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
- if (!scanPtr.p->scanKeyinfoFlag){
- jam();
- /** ---------------------------------------------------------------------
- * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
- * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
- * ---------------------------------------------------------------------- */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = operationRecPtr.p->localdata[0];
- signal->theData[4] = operationRecPtr.p->localdata[1];
- signal->theData[5] = fragrecptr.p->localkeylen;
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6);
- return;
- }//if
-
- if (fragrecptr.p->keyLength != 0) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = operationRecPtr.p->localdata[0];
- signal->theData[4] = operationRecPtr.p->localdata[1];
- signal->theData[5] = fragrecptr.p->localkeylen;
- signal->theData[6] = fragrecptr.p->keyLength;
- signal->theData[7] = operationRecPtr.p->keydata[0];
- signal->theData[8] = operationRecPtr.p->keydata[1];
- signal->theData[9] = operationRecPtr.p->keydata[2];
- signal->theData[10] = operationRecPtr.p->keydata[3];
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11);
- if (fragrecptr.p->keyLength > ZKEYINKEYREQ) {
- jam();
- /* = 4 */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = fragrecptr.p->keyLength - ZKEYINKEYREQ;
- signal->theData[4] = operationRecPtr.p->keydata[4];
- signal->theData[5] = operationRecPtr.p->keydata[5];
- signal->theData[6] = operationRecPtr.p->keydata[6];
- signal->theData[7] = operationRecPtr.p->keydata[7];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO, signal, 8);
- return;
- }//if
- } else {
- jam();
- sendScaninfo(signal);
- return;
- }//if
-}//Dbacc::sendNextScanConf()
-
-/* --------------------------------------------------------------------------------- */
-/* SEND_SCANINFO */
-/* DESCRIPTION: SCAN AN ELEMENT OF A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendScaninfo(Signal* signal)
-{
- DirRangePtr ssiOverflowrangeptr;
- DirectoryarrayPtr ssiOverflowDirptr;
- Page8Ptr ssiPageptr;
- Uint32 tssiPageIndex;
- Uint32 tssiPagedir;
- Uint32 tssiKeyLen;
- Uint32 tssiStartIndex;
- Uint32 tssiIndexValue;
- Uint32 tssiTmp;
-
- Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
-
- tssiPageIndex = operationRecPtr.p->keydata[0] & 0x3ff;
- tssiPagedir = operationRecPtr.p->keydata[0] >> 10;
- ssiOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(ssiOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tssiPagedir >> 8), 256);
- ssiOverflowDirptr.i = ssiOverflowrangeptr.p->dirArray[tssiPagedir >> 8];
- ptrCheckGuard(ssiOverflowDirptr, cdirarraysize, directoryarray);
- ssiPageptr.i = ssiOverflowDirptr.p->pagep[tssiPagedir & 0xff];
- ptrCheckGuard(ssiPageptr, cpagesize, page8);
- arrGuard(ZWORDS_IN_PAGE - tssiPageIndex, 2048);
- tssiIndexValue = ssiPageptr.p->word32[ZWORDS_IN_PAGE - tssiPageIndex];
- tssiStartIndex = tssiIndexValue & 0xffff;
- tssiKeyLen = tssiIndexValue >> 16;
+ jam();
+ /** ---------------------------------------------------------------------
+ * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
+ * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
+ * ---------------------------------------------------------------------- */
signal->theData[0] = scanPtr.p->scanUserptr;
signal->theData[1] = operationRecPtr.i;
signal->theData[2] = operationRecPtr.p->fid;
signal->theData[3] = operationRecPtr.p->localdata[0];
signal->theData[4] = operationRecPtr.p->localdata[1];
signal->theData[5] = fragrecptr.p->localkeylen;
- signal->theData[6] = tssiKeyLen;
- arrGuard(tssiStartIndex + 3, 2048);
- signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex];
- signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 1];
- signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 2];
- signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 3];
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11);
- if (tssiKeyLen > 4) {
- tssiKeyLen = tssiKeyLen - 4;
- tssiStartIndex = tssiStartIndex + 4;
- SSI_LOOP_10:
- jamEntry();
- if (tssiKeyLen > ZMAXSCANSIGNALLEN) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = ZMAXSCANSIGNALLEN;
- arrGuard(tssiStartIndex + 19, 2048);
- signal->theData[4] = ssiPageptr.p->word32[tssiStartIndex];
- signal->theData[5] = ssiPageptr.p->word32[tssiStartIndex + 1];
- signal->theData[6] = ssiPageptr.p->word32[tssiStartIndex + 2];
- signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex + 3];
- signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 4];
- signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 5];
- signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 6];
- signal->theData[11] = ssiPageptr.p->word32[tssiStartIndex + 7];
- signal->theData[12] = ssiPageptr.p->word32[tssiStartIndex + 8];
- signal->theData[13] = ssiPageptr.p->word32[tssiStartIndex + 9];
- signal->theData[14] = ssiPageptr.p->word32[tssiStartIndex + 10];
- signal->theData[15] = ssiPageptr.p->word32[tssiStartIndex + 11];
- signal->theData[16] = ssiPageptr.p->word32[tssiStartIndex + 12];
- signal->theData[17] = ssiPageptr.p->word32[tssiStartIndex + 13];
- signal->theData[18] = ssiPageptr.p->word32[tssiStartIndex + 14];
- signal->theData[19] = ssiPageptr.p->word32[tssiStartIndex + 15];
- signal->theData[20] = ssiPageptr.p->word32[tssiStartIndex + 16];
- signal->theData[21] = ssiPageptr.p->word32[tssiStartIndex + 17];
- signal->theData[22] = ssiPageptr.p->word32[tssiStartIndex + 18];
- signal->theData[23] = ssiPageptr.p->word32[tssiStartIndex + 19];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24);
- tssiStartIndex = tssiStartIndex + ZMAXSCANSIGNALLEN;
- tssiKeyLen = tssiKeyLen - ZMAXSCANSIGNALLEN;
- goto SSI_LOOP_10;
- } else {
- jam();
- ndbrequire((tssiStartIndex + tssiKeyLen) <= 2048);
- for (tssiTmp = 0; tssiTmp < tssiKeyLen; tssiTmp++) {
- ckeys[tssiTmp] = ssiPageptr.p->word32[tssiStartIndex + tssiTmp];
- }//for
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- /* LOCAL FRAGMENT IDENTITY */
- signal->theData[3] = tssiKeyLen;
- signal->theData[4] = ckeys[0];
- signal->theData[5] = ckeys[1];
- signal->theData[6] = ckeys[2];
- signal->theData[7] = ckeys[3];
- signal->theData[8] = ckeys[4];
- signal->theData[9] = ckeys[5];
- signal->theData[10] = ckeys[6];
- signal->theData[11] = ckeys[7];
- signal->theData[12] = ckeys[8];
- signal->theData[13] = ckeys[9];
- signal->theData[14] = ckeys[10];
- signal->theData[15] = ckeys[11];
- signal->theData[16] = ckeys[12];
- signal->theData[17] = ckeys[13];
- signal->theData[18] = ckeys[14];
- signal->theData[19] = ckeys[15];
- signal->theData[20] = ckeys[16];
- signal->theData[21] = ckeys[17];
- signal->theData[22] = ckeys[18];
- signal->theData[23] = ckeys[19];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24);
- }//if
- }//if
-}//Dbacc::sendScaninfo()
+ EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6);
+ return;
+}//Dbacc::sendNextScanConf()
/*---------------------------------------------------------------------------
* sendScanHbRep
@@ -13202,9 +11284,9 @@ void Dbacc::seizeSrVerRec(Signal* signal)
/* --------------------------------------------------------------------------------- */
/* SEND_SYSTEMERROR */
/* --------------------------------------------------------------------------------- */
-void Dbacc::sendSystemerror(Signal* signal)
+void Dbacc::sendSystemerror(Signal* signal, int line)
{
- progError(0, 0);
+ progError(line, NDBD_EXIT_PRGERR);
}//Dbacc::sendSystemerror()
/* --------------------------------------------------------------------------------- */
@@ -13265,7 +11347,7 @@ void Dbacc::takeRecOutOfFreeOverpage(Signal* signal)
void
Dbacc::reportMemoryUsage(Signal* signal, int gth){
- signal->theData[0] = EventReport::MemoryUsage;
+ signal->theData[0] = NDB_LE_MemoryUsage;
signal->theData[1] = gth;
signal->theData[2] = sizeof(* rpPageptr.p);
signal->theData[3] = cnoOfAllocatedPages;
@@ -13315,13 +11397,12 @@ Dbacc::execDUMP_STATE_ORD(Signal* signal)
scanPtr.p->minBucketIndexToRescan,
scanPtr.p->maxBucketIndexToRescan);
infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, "
- "scanMask=%d scanLockMode=%d, keyInfoFlag=%d",
+ "scanMask=%d scanLockMode=%d",
scanPtr.p->scanBucketState,
scanPtr.p->scanLockHeld,
scanPtr.p->scanUserblockref,
scanPtr.p->scanMask,
- scanPtr.p->scanLockMode,
- scanPtr.p->scanKeyinfoFlag);
+ scanPtr.p->scanLockMode);
return;
}
diff --git a/ndb/src/kernel/blocks/dbacc/Makefile.am b/ndb/src/kernel/blocks/dbacc/Makefile.am
index e44524c3edd..ca1b1efac37 100644
--- a/ndb/src/kernel/blocks/dbacc/Makefile.am
+++ b/ndb/src/kernel/blocks/dbacc/Makefile.am
@@ -3,6 +3,8 @@ noinst_LIBRARIES = libdbacc.a
libdbacc_a_SOURCES = DbaccInit.cpp DbaccMain.cpp
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/kernel/blocks/dbtup
+
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_kernel.mk.am
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index 2bb429aeabc..efd519339f7 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -27,6 +27,7 @@
#include <SectionReader.hpp>
#include <SimpleProperties.hpp>
#include <AttributeHeader.hpp>
+#include <KeyDescriptor.hpp>
#include <signaldata/DictSchemaInfo.hpp>
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/DropTabFile.hpp>
@@ -202,6 +203,11 @@ void Dbdict::execCONTINUEB(Signal* signal)
sendGetTabResponse(signal);
break;
+ case ZDICT_LOCK_POLL:
+ jam();
+ checkDictLockQueue(signal, true);
+ break;
+
default :
ndbrequire(false);
break;
@@ -228,7 +234,7 @@ void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
8 * ZSIZE_OF_PAGES_IN_WORDS);
w.first();
- packTableIntoPagesImpl(w, tablePtr);
+ packTableIntoPagesImpl(w, tablePtr, signal);
Uint32 wordsOfTable = w.getWordsUsed();
Uint32 pagesUsed =
@@ -257,7 +263,8 @@ void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
void
Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
- TableRecordPtr tablePtr){
+ TableRecordPtr tablePtr,
+ Signal* signal){
w.add(DictTabInfo::TableName, tablePtr.p->tableName);
w.add(DictTabInfo::TableId, tablePtr.i);
@@ -278,9 +285,36 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
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);
+ w.add(DictTabInfo::MaxRowsLow, tablePtr.p->maxRowsLow);
+ w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
+ w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
+ w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
+
+ if(!signal)
+ {
+ w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
+ }
+ else
+ {
+ Uint32 * theData = signal->getDataPtrSend();
+ CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
+ req->senderRef = 0;
+ req->senderData = RNIL;
+ req->fragmentationType = tablePtr.p->fragmentType;
+ req->noOfFragments = 0;
+ req->fragmentNode = 0;
+ req->primaryTableId = tablePtr.i;
+ EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
+ CreateFragmentationReq::SignalLength);
+ if(signal->theData[0] == 0)
+ {
+ Uint16 *data = (Uint16*)&signal->theData[25];
+ Uint32 count = 2 + data[0] * data[1];
+ w.add(DictTabInfo::FragmentDataLen, 2*count);
+ w.add(DictTabInfo::FragmentData, data, 2*count);
+ }
+ }
if (tablePtr.p->primaryTableId != RNIL){
TableRecordPtr primTab;
@@ -311,18 +345,14 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
const Uint32 attrSize = AttributeDescriptor::getSize(desc);
const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
const Uint32 nullable = AttributeDescriptor::getNullable(desc);
- const Uint32 DGroup = AttributeDescriptor::getDGroup(desc);
const Uint32 DKey = AttributeDescriptor::getDKey(desc);
- const Uint32 attrStoredInd = AttributeDescriptor::getStoredInTup(desc);
- w.add(DictTabInfo::AttributeType, attrType);
+ // AttributeType deprecated
w.add(DictTabInfo::AttributeSize, attrSize);
w.add(DictTabInfo::AttributeArraySize, arraySize);
w.add(DictTabInfo::AttributeNullableFlag, nullable);
- w.add(DictTabInfo::AttributeDGroup, DGroup);
w.add(DictTabInfo::AttributeDKey, DKey);
- w.add(DictTabInfo::AttributeStoredInd, attrStoredInd);
- w.add(DictTabInfo::AttributeExtType, attrPtr.p->extType);
+ w.add(DictTabInfo::AttributeExtType, attrType);
w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
@@ -370,7 +400,7 @@ void Dbdict::execFSCLOSECONF(Signal* signal)
closeWriteTableConf(signal, fsPtr);
break;
case FsConnectRecord::OPEN_READ_SCHEMA2:
- openSchemaFile(signal, 1, fsPtr.i, false);
+ openSchemaFile(signal, 1, fsPtr.i, false, false);
break;
default:
jamLine((fsPtr.p->fsState & 0xFFF));
@@ -631,7 +661,7 @@ void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
+ fsRWReq->varIndex = ZBAT_TABLE_FILE;
fsRWReq->numberOfPages = c_writeTableRecord.noOfPages;
fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
@@ -708,7 +738,7 @@ void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
+ fsRWReq->varIndex = ZBAT_TABLE_FILE;
fsRWReq->numberOfPages = c_readTableRecord.noOfPages;
fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
@@ -774,11 +804,9 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
SchemaFile::TableEntry* te, Callback* callback){
jam();
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
ndbrequire(tableId < c_tableRecordPool.getSize());
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tableId);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
SchemaFile::TableState newState =
(SchemaFile::TableState)te->m_tableState;
@@ -825,12 +853,15 @@ Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
ndbrequire(ok);
* tableEntry = * te;
- computeChecksum((SchemaFile*)pagePtr.p);
+ computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = false;
+ c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
+ c_writeSchemaRecord.noOfPages = 1;
c_writeSchemaRecord.m_callback = * callback;
startWriteSchemaFile(signal);
@@ -841,14 +872,15 @@ void Dbdict::startWriteSchemaFile(Signal* signal)
FsConnectRecordPtr fsPtr;
c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
- openSchemaFile(signal, 0, fsPtr.i, true);
+ openSchemaFile(signal, 0, fsPtr.i, true, c_writeSchemaRecord.newFile);
c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
}//Dbdict::startWriteSchemaFile()
void Dbdict::openSchemaFile(Signal* signal,
Uint32 fileNo,
Uint32 fsConPtr,
- bool writeFlag)
+ bool writeFlag,
+ bool newFile)
{
FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
fsOpenReq->userReference = reference();
@@ -857,9 +889,11 @@ void Dbdict::openSchemaFile(Signal* signal,
jam();
fsOpenReq->fileFlags =
FsOpenReq::OM_WRITEONLY |
- FsOpenReq::OM_TRUNCATE |
- FsOpenReq::OM_CREATE |
FsOpenReq::OM_SYNC;
+ if (newFile)
+ fsOpenReq->fileFlags |=
+ FsOpenReq::OM_TRUNCATE |
+ FsOpenReq::OM_CREATE;
} else {
jam();
fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
@@ -884,6 +918,12 @@ void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
{
FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
+ // check write record
+ WriteSchemaRecord & wr = c_writeSchemaRecord;
+ ndbrequire(wr.pageId == (wr.pageId != 0) * NDB_SF_MAX_PAGES);
+ ndbrequire(wr.noOfPages != 0);
+ ndbrequire(wr.firstPage + wr.noOfPages <= NDB_SF_MAX_PAGES);
+
fsRWReq->filePointer = filePtr;
fsRWReq->userReference = reference();
fsRWReq->userPointer = fsConPtr;
@@ -891,11 +931,11 @@ void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
- fsRWReq->numberOfPages = 1;
-// Write from memory page
- fsRWReq->data.arrayOfPages.varIndex = c_writeSchemaRecord.pageId;
- fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
+ fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
+ fsRWReq->numberOfPages = wr.noOfPages;
+ // Write from memory page
+ fsRWReq->data.arrayOfPages.varIndex = wr.pageId + wr.firstPage;
+ fsRWReq->data.arrayOfPages.fileOffset = wr.firstPage;
sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
}//writeSchemaFile()
@@ -925,7 +965,7 @@ void Dbdict::closeWriteSchemaConf(Signal* signal,
if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
jam();
fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
- openSchemaFile(signal, 1, fsPtr.i, true);
+ openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
return;
}
ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
@@ -943,20 +983,26 @@ void Dbdict::startReadSchemaFile(Signal* signal)
FsConnectRecordPtr fsPtr;
c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
- openSchemaFile(signal, 0, fsPtr.i, false);
+ openSchemaFile(signal, 0, fsPtr.i, false, false);
}//Dbdict::startReadSchemaFile()
void Dbdict::openReadSchemaRef(Signal* signal,
FsConnectRecordPtr fsPtr)
{
fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
- openSchemaFile(signal, 1, fsPtr.i, false);
+ openSchemaFile(signal, 1, fsPtr.i, false, false);
}//Dbdict::openReadSchemaRef()
void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
{
FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
+ // check read record
+ ReadSchemaRecord & rr = c_readSchemaRecord;
+ ndbrequire(rr.pageId == (rr.pageId != 0) * NDB_SF_MAX_PAGES);
+ ndbrequire(rr.noOfPages != 0);
+ ndbrequire(rr.firstPage + rr.noOfPages <= NDB_SF_MAX_PAGES);
+
fsRWReq->filePointer = filePtr;
fsRWReq->userReference = reference();
fsRWReq->userPointer = fsConPtr;
@@ -964,10 +1010,10 @@ void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
FsReadWriteReq::fsFormatArrayOfPages);
- fsRWReq->varIndex = ZALLOCATE;
- fsRWReq->numberOfPages = 1;
- fsRWReq->data.arrayOfPages.varIndex = c_readSchemaRecord.pageId;
- fsRWReq->data.arrayOfPages.fileOffset = 0;
+ fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
+ fsRWReq->numberOfPages = rr.noOfPages;
+ fsRWReq->data.arrayOfPages.varIndex = rr.pageId + rr.firstPage;
+ fsRWReq->data.arrayOfPages.fileOffset = rr.firstPage;
sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
}//readSchemaFile()
@@ -985,20 +1031,61 @@ void Dbdict::readSchemaConf(Signal* signal,
jam();
crashInd = true;
}//if
- PageRecordPtr tmpPagePtr;
- c_pageRecordArray.getPtr(tmpPagePtr, c_readSchemaRecord.pageId);
- Uint32 sz = ZSIZE_OF_PAGES_IN_WORDS;
- Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
+ ReadSchemaRecord & rr = c_readSchemaRecord;
+ XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
- ndbrequire((chk == 0) || !crashInd);
+ if (rr.schemaReadState == ReadSchemaRecord::INITIAL_READ_HEAD) {
+ jam();
+ ndbrequire(rr.firstPage == 0);
+ SchemaFile * sf = &xsf->schemaPage[0];
+ Uint32 noOfPages;
+ if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) {
+ jam();
+ const Uint32 pageSize_old = 32 * 1024;
+ noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1;
+ } else {
+ noOfPages = sf->FileSize / NDB_SF_PAGE_SIZE - 1;
+ }
+ rr.schemaReadState = ReadSchemaRecord::INITIAL_READ;
+ if (noOfPages != 0) {
+ rr.firstPage = 1;
+ rr.noOfPages = noOfPages;
+ readSchemaFile(signal, fsPtr.p->filePtr, fsPtr.i);
+ return;
+ }
+ }
+
+ SchemaFile * sf0 = &xsf->schemaPage[0];
+ xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE;
- if (chk != 0){
+ if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 &&
+ ! convertSchemaFileTo_5_0_6(xsf)) {
jam();
+ ndbrequire(! crashInd);
ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
readSchemaRef(signal, fsPtr);
return;
- }//if
+ }
+
+ for (Uint32 n = 0; n < xsf->noOfPages; n++) {
+ SchemaFile * sf = &xsf->schemaPage[n];
+ bool ok =
+ memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) == 0 &&
+ sf->FileSize != 0 &&
+ sf->FileSize % NDB_SF_PAGE_SIZE == 0 &&
+ sf->FileSize == sf0->FileSize &&
+ sf->PageNumber == n &&
+ computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) == 0;
+ ndbrequire(ok || !crashInd);
+ if (! ok) {
+ jam();
+ ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
+ readSchemaRef(signal, fsPtr);
+ return;
+ }
+ }
+
fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
return;
@@ -1025,7 +1112,27 @@ void Dbdict::closeReadSchemaConf(Signal* signal,
switch(state) {
case ReadSchemaRecord::INITIAL_READ :
jam();
- sendNDB_STTORRY(signal);
+ {
+ // write back both copies
+
+ ndbrequire(c_writeSchemaRecord.inUse == false);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0 ];
+ Uint32 noOfPages =
+ (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1) /
+ NDB_SF_PAGE_ENTRIES;
+ resizeSchemaFile(xsf, noOfPages);
+
+ c_writeSchemaRecord.inUse = true;
+ c_writeSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
+ c_writeSchemaRecord.newFile = true;
+ c_writeSchemaRecord.firstPage = 0;
+ c_writeSchemaRecord.noOfPages = xsf->noOfPages;
+
+ c_writeSchemaRecord.m_callback.m_callbackFunction =
+ safe_cast(&Dbdict::initSchemaFile_conf);
+
+ startWriteSchemaFile(signal);
+ }
break;
default :
@@ -1035,6 +1142,54 @@ void Dbdict::closeReadSchemaConf(Signal* signal,
}//switch
}//Dbdict::closeReadSchemaConf()
+bool
+Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
+{
+ const Uint32 pageSize_old = 32 * 1024;
+ Uint32 page_old[pageSize_old >> 2];
+ SchemaFile * sf_old = (SchemaFile *)page_old;
+
+ if (xsf->noOfPages * NDB_SF_PAGE_SIZE != pageSize_old)
+ return false;
+ SchemaFile * sf0 = &xsf->schemaPage[0];
+ memcpy(sf_old, sf0, pageSize_old);
+
+ // init max number new pages needed
+ xsf->noOfPages = (sf_old->NoOfTableEntries + NDB_SF_PAGE_ENTRIES - 1) /
+ NDB_SF_PAGE_ENTRIES;
+ initSchemaFile(xsf, 0, xsf->noOfPages, true);
+
+ Uint32 noOfPages = 1;
+ Uint32 n, i, j;
+ for (n = 0; n < xsf->noOfPages; n++) {
+ jam();
+ for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
+ j = n * NDB_SF_PAGE_ENTRIES + i;
+ if (j >= sf_old->NoOfTableEntries)
+ continue;
+ const SchemaFile::TableEntry_old & te_old = sf_old->TableEntries_old[j];
+ if (te_old.m_tableState == SchemaFile::INIT ||
+ te_old.m_tableState == SchemaFile::DROP_TABLE_COMMITTED ||
+ te_old.m_noOfPages == 0)
+ continue;
+ SchemaFile * sf = &xsf->schemaPage[n];
+ SchemaFile::TableEntry & te = sf->TableEntries[i];
+ te.m_tableState = te_old.m_tableState;
+ te.m_tableVersion = te_old.m_tableVersion;
+ te.m_tableType = te_old.m_tableType;
+ te.m_info_words = te_old.m_noOfPages * ZSIZE_OF_PAGES_IN_WORDS -
+ ZPAGE_HEADER_SIZE;
+ te.m_gcp = te_old.m_gcp;
+ if (noOfPages < n)
+ noOfPages = n;
+ }
+ }
+ xsf->noOfPages = noOfPages;
+ initSchemaFile(xsf, 0, xsf->noOfPages, false);
+
+ return true;
+}
+
/* **************************************************************** */
/* ---------------------------------------------------------------- */
/* MODULE: INITIALISATION MODULE ------------------------- */
@@ -1055,14 +1210,12 @@ Dbdict::Dbdict(const class Configuration & conf):
c_opDropIndex(c_opRecordPool),
c_opAlterIndex(c_opRecordPool),
c_opBuildIndex(c_opRecordPool),
- c_opCreateEvent(c_opRecordPool),
- c_opSubEvent(c_opRecordPool),
- c_opDropEvent(c_opRecordPool),
- c_opSignalUtil(c_opRecordPool),
c_opCreateTrigger(c_opRecordPool),
c_opDropTrigger(c_opRecordPool),
c_opAlterTrigger(c_opRecordPool),
- c_opRecordSequence(0)
+ c_opRecordSequence(0),
+ c_dictLockQueue(c_dictLockPool),
+ c_dictLockPoll(false)
{
BLOCK_CONSTRUCTOR(Dbdict);
@@ -1116,44 +1269,6 @@ Dbdict::Dbdict(const class Configuration & conf):
addRecSignal(GSN_BUILDINDXCONF, &Dbdict::execBUILDINDXCONF);
addRecSignal(GSN_BUILDINDXREF, &Dbdict::execBUILDINDXREF);
- // Util signals
- addRecSignal(GSN_UTIL_PREPARE_CONF, &Dbdict::execUTIL_PREPARE_CONF);
- addRecSignal(GSN_UTIL_PREPARE_REF, &Dbdict::execUTIL_PREPARE_REF);
-
- addRecSignal(GSN_UTIL_EXECUTE_CONF, &Dbdict::execUTIL_EXECUTE_CONF);
- addRecSignal(GSN_UTIL_EXECUTE_REF, &Dbdict::execUTIL_EXECUTE_REF);
-
- addRecSignal(GSN_UTIL_RELEASE_CONF, &Dbdict::execUTIL_RELEASE_CONF);
- addRecSignal(GSN_UTIL_RELEASE_REF, &Dbdict::execUTIL_RELEASE_REF);
-
- // Event signals
- addRecSignal(GSN_CREATE_EVNT_REQ, &Dbdict::execCREATE_EVNT_REQ);
- addRecSignal(GSN_CREATE_EVNT_CONF, &Dbdict::execCREATE_EVNT_CONF);
- addRecSignal(GSN_CREATE_EVNT_REF, &Dbdict::execCREATE_EVNT_REF);
-
- addRecSignal(GSN_CREATE_SUBID_CONF, &Dbdict::execCREATE_SUBID_CONF);
- addRecSignal(GSN_CREATE_SUBID_REF, &Dbdict::execCREATE_SUBID_REF);
-
- addRecSignal(GSN_SUB_CREATE_CONF, &Dbdict::execSUB_CREATE_CONF);
- addRecSignal(GSN_SUB_CREATE_REF, &Dbdict::execSUB_CREATE_REF);
-
- addRecSignal(GSN_SUB_START_REQ, &Dbdict::execSUB_START_REQ);
- addRecSignal(GSN_SUB_START_CONF, &Dbdict::execSUB_START_CONF);
- addRecSignal(GSN_SUB_START_REF, &Dbdict::execSUB_START_REF);
-
- addRecSignal(GSN_SUB_STOP_REQ, &Dbdict::execSUB_STOP_REQ);
- addRecSignal(GSN_SUB_STOP_CONF, &Dbdict::execSUB_STOP_CONF);
- addRecSignal(GSN_SUB_STOP_REF, &Dbdict::execSUB_STOP_REF);
-
- addRecSignal(GSN_SUB_SYNC_CONF, &Dbdict::execSUB_SYNC_CONF);
- addRecSignal(GSN_SUB_SYNC_REF, &Dbdict::execSUB_SYNC_REF);
-
- addRecSignal(GSN_DROP_EVNT_REQ, &Dbdict::execDROP_EVNT_REQ);
-
- addRecSignal(GSN_SUB_REMOVE_REQ, &Dbdict::execSUB_REMOVE_REQ);
- addRecSignal(GSN_SUB_REMOVE_CONF, &Dbdict::execSUB_REMOVE_CONF);
- addRecSignal(GSN_SUB_REMOVE_REF, &Dbdict::execSUB_REMOVE_REF);
-
// Trigger signals
addRecSignal(GSN_CREATE_TRIG_REQ, &Dbdict::execCREATE_TRIG_REQ);
addRecSignal(GSN_CREATE_TRIG_CONF, &Dbdict::execCREATE_TRIG_CONF);
@@ -1206,6 +1321,9 @@ Dbdict::Dbdict(const class Configuration & conf):
addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Dbdict::execBACKUP_FRAGMENT_REQ);
+
+ addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
+ addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
}//Dbdict::Dbdict()
Dbdict::~Dbdict()
@@ -1306,6 +1424,7 @@ void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
void Dbdict::initSchemaRecord()
{
c_schemaRecord.schemaPage = RNIL;
+ c_schemaRecord.oldSchemaPage = RNIL;
}//Dbdict::initSchemaRecord()
void Dbdict::initRestartRecord()
@@ -1327,10 +1446,10 @@ void Dbdict::initNodeRecords()
void Dbdict::initPageRecords()
{
- c_schemaRecord.schemaPage = ZMAX_PAGES_OF_TABLE_DEFINITION;
- c_schemaRecord.oldSchemaPage = ZMAX_PAGES_OF_TABLE_DEFINITION + 1;
- c_retrieveRecord.retrievePage = ZMAX_PAGES_OF_TABLE_DEFINITION + 2;
- ndbrequire(ZNUMBER_OF_PAGES >= (2 * ZMAX_PAGES_OF_TABLE_DEFINITION + 2));
+ c_retrieveRecord.retrievePage = ZMAX_PAGES_OF_TABLE_DEFINITION;
+ ndbrequire(ZNUMBER_OF_PAGES >= (ZMAX_PAGES_OF_TABLE_DEFINITION + 1));
+ c_schemaRecord.schemaPage = 0;
+ c_schemaRecord.oldSchemaPage = NDB_SF_MAX_PAGES;
}//Dbdict::initPageRecords()
void Dbdict::initTableRecords()
@@ -1360,9 +1479,7 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->tableVersion = (Uint32)-1;
tablePtr.p->tabState = TableRecord::NOT_DEFINED;
tablePtr.p->tabReturnState = TableRecord::TRS_IDLE;
- tablePtr.p->storageType = DictTabInfo::MainMemory;
tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
- tablePtr.p->fragmentKeyType = DictTabInfo::PrimaryKey;
memset(tablePtr.p->tableName, 0, sizeof(tablePtr.p->tableName));
tablePtr.p->gciTableCreated = 0;
tablePtr.p->noOfAttributes = ZNIL;
@@ -1380,6 +1497,10 @@ void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
tablePtr.p->minLoadFactor = 70;
tablePtr.p->noOfPrimkey = 1;
tablePtr.p->tupKeyLength = 1;
+ tablePtr.p->maxRowsLow = 0;
+ tablePtr.p->maxRowsHigh = 0;
+ tablePtr.p->minRowsLow = 0;
+ tablePtr.p->minRowsHigh = 0;
tablePtr.p->storedTable = true;
tablePtr.p->tableType = DictTabInfo::UserTable;
tablePtr.p->primaryTableId = RNIL;
@@ -1599,18 +1720,16 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
c_nodes.setSize(MAX_NODES);
c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
+ c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
c_tableRecordPool.setSize(tablerecSize);
c_tableRecordHash.setSize(tablerecSize);
+ g_key_descriptor_pool.setSize(tablerecSize);
c_triggerRecordPool.setSize(c_maxNoOfTriggers);
c_triggerRecordHash.setSize(c_maxNoOfTriggers);
c_opRecordPool.setSize(256); // XXX need config params
c_opCreateTable.setSize(8);
c_opDropTable.setSize(8);
c_opCreateIndex.setSize(8);
- c_opCreateEvent.setSize(8);
- c_opSubEvent.setSize(8);
- c_opDropEvent.setSize(8);
- c_opSignalUtil.setSize(8);
c_opDropIndex.setSize(8);
c_opAlterIndex.setSize(8);
c_opBuildIndex.setSize(8);
@@ -1618,11 +1737,24 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
c_opDropTrigger.setSize(8);
c_opAlterTrigger.setSize(8);
+ c_dictLockPool.setSize(32);
+
+ // Initialize schema file copies
+ c_schemaFile[0].schemaPage =
+ (SchemaFile*)c_schemaPageRecordArray.getPtr(0 * NDB_SF_MAX_PAGES);
+ c_schemaFile[0].noOfPages = 0;
+ c_schemaFile[1].schemaPage =
+ (SchemaFile*)c_schemaPageRecordArray.getPtr(1 * NDB_SF_MAX_PAGES);
+ c_schemaFile[1].noOfPages = 0;
+
// Initialize BAT for interface to file system
- PageRecordPtr pageRecPtr;
- c_pageRecordArray.getPtr(pageRecPtr, 0);
NewVARIABLE* bat = allocateBat(2);
- bat[1].WA = &pageRecPtr.p->word[0];
+ bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
+ bat[0].nrr = 2 * NDB_SF_MAX_PAGES;
+ bat[0].ClusterSize = NDB_SF_PAGE_SIZE;
+ bat[0].bits.q = NDB_SF_PAGE_SIZE_IN_WORDS_LOG2;
+ bat[0].bits.v = 5; // 32 bits per element
+ bat[1].WA = &c_pageRecordArray.getPtr(0)->word[0];
bat[1].nrr = ZNUMBER_OF_PAGES;
bat[1].ClusterSize = ZSIZE_OF_PAGES_IN_WORDS * 4;
bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
@@ -1767,16 +1899,23 @@ void Dbdict::execHOT_SPAREREP(Signal* signal)
void Dbdict::initSchemaFile(Signal* signal)
{
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- SchemaFile * schemaFile = (SchemaFile *)pagePtr.p;
- initSchemaFile(schemaFile, 4 * ZSIZE_OF_PAGES_IN_WORDS);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ xsf->noOfPages = (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1)
+ / NDB_SF_PAGE_ENTRIES;
+ initSchemaFile(xsf, 0, xsf->noOfPages, true);
+ // init alt copy too for INR
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ oldxsf->noOfPages = xsf->noOfPages;
+ memcpy(&oldxsf->schemaPage[0], &xsf->schemaPage[0], xsf->schemaPage[0].FileSize);
if (c_initialStart || c_initialNodeRestart) {
jam();
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = true;
+ c_writeSchemaRecord.firstPage = 0;
+ c_writeSchemaRecord.noOfPages = xsf->noOfPages;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::initSchemaFile_conf);
@@ -1786,7 +1925,9 @@ void Dbdict::initSchemaFile(Signal* signal)
jam();
ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
- c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ;
+ c_readSchemaRecord.firstPage = 0;
+ c_readSchemaRecord.noOfPages = 1;
+ c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
startReadSchemaFile(signal);
} else {
ndbrequire(false);
@@ -1925,7 +2066,7 @@ void Dbdict::execDICTSTARTREQ(Signal* signal)
safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
c_restartRecord.activeTable = 0;
- c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage;
+ c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage; // ugly
checkSchemaStatus(signal);
}//execDICTSTARTREQ()
@@ -1934,15 +2075,13 @@ Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
Uint32 callbackData,
Uint32 returnCode){
- c_schemaRecord.schemaPage = ZMAX_PAGES_OF_TABLE_DEFINITION;
+ c_schemaRecord.schemaPage = 0; // ugly
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ ndbrequire(oldxsf->noOfPages != 0);
LinearSectionPtr ptr[3];
-
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.oldSchemaPage);
-
- ptr[0].p = &pagePtr.p->word[0];
- ptr[0].sz = ZSIZE_OF_PAGES_IN_WORDS;
+ ptr[0].p = (Uint32*)&oldxsf->schemaPage[0];
+ ptr[0].sz = oldxsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
c_sendSchemaRecord.m_SCHEMAINFO_Counter = c_aliveNodes;
NodeReceiverGroup rg(DBDICT, c_aliveNodes);
@@ -1958,10 +2097,10 @@ Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
1,
c);
- PageRecordPtr newPagePtr;
- c_pageRecordArray.getPtr(newPagePtr, c_schemaRecord.schemaPage);
- memcpy(&newPagePtr.p->word[0], &pagePtr.p->word[0],
- 4 * ZSIZE_OF_PAGES_IN_WORDS);
+ XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ newxsf->noOfPages = oldxsf->noOfPages;
+ memcpy(&newxsf->schemaPage[0], &oldxsf->schemaPage[0],
+ oldxsf->noOfPages * NDB_SF_PAGE_SIZE);
signal->theData[0] = getOwnNodeId();
sendSignal(reference(), GSN_SCHEMA_INFOCONF, signal, 1, JBB);
@@ -1978,11 +2117,11 @@ Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
LinearSectionPtr ptr[3];
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ ndbrequire(xsf->noOfPages != 0);
- ptr[0].p = &pagePtr.p->word[0];
- ptr[0].sz = ZSIZE_OF_PAGES_IN_WORDS;
+ ptr[0].p = (Uint32*)&xsf->schemaPage[0];
+ ptr[0].sz = xsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
Callback c = { safe_cast(&Dbdict::sendSchemaComplete), 0 };
sendFragmentedSignal(ref,
@@ -2024,12 +2163,22 @@ void Dbdict::execSCHEMA_INFO(Signal* signal)
SegmentedSectionPtr schemaDataPtr;
signal->getSection(schemaDataPtr, 0);
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- copy(&pagePtr.p->word[0], schemaDataPtr);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ ndbrequire(schemaDataPtr.sz % NDB_SF_PAGE_SIZE_IN_WORDS == 0);
+ xsf->noOfPages = schemaDataPtr.sz / NDB_SF_PAGE_SIZE_IN_WORDS;
+ copy((Uint32*)&xsf->schemaPage[0], schemaDataPtr);
releaseSections(signal);
+
+ SchemaFile * sf0 = &xsf->schemaPage[0];
+ if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) {
+ bool ok = convertSchemaFileTo_5_0_6(xsf);
+ ndbrequire(ok);
+ }
- validateChecksum((SchemaFile*)pagePtr.p);
+ validateChecksum(xsf);
+
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ resizeSchemaFile(xsf, oldxsf->noOfPages);
ndbrequire(signal->getSendersBlockRef() != reference());
@@ -2054,7 +2203,11 @@ Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = true;
+ c_writeSchemaRecord.firstPage = 0;
+ c_writeSchemaRecord.noOfPages = xsf->noOfPages;
c_writeSchemaRecord.m_callback.m_callbackData = 0;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::restart_writeSchemaConf);
@@ -2103,20 +2256,18 @@ void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
void Dbdict::checkSchemaStatus(Signal* signal)
{
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
- PageRecordPtr oldPagePtr;
- c_pageRecordArray.getPtr(oldPagePtr, c_schemaRecord.oldSchemaPage);
+ XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
+ ndbrequire(newxsf->noOfPages == oldxsf->noOfPages);
+ const Uint32 noOfEntries = newxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
- for (; c_restartRecord.activeTable < MAX_TABLES;
+ for (; c_restartRecord.activeTable < noOfEntries;
c_restartRecord.activeTable++) {
jam();
Uint32 tableId = c_restartRecord.activeTable;
- SchemaFile::TableEntry *newEntry = getTableEntry(pagePtr.p, tableId);
- SchemaFile::TableEntry *oldEntry = getTableEntry(oldPagePtr.p, tableId,
- true);
+ SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId);
+ SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId);
SchemaFile::TableState schemaState =
(SchemaFile::TableState)newEntry->m_tableState;
SchemaFile::TableState oldSchemaState =
@@ -2247,7 +2398,7 @@ void Dbdict::checkSchemaStatus(Signal* signal)
return;
}//if
}
- ndbrequire(ok);
+ ndbrequire(ok);
break;
}
case SchemaFile::DROP_TABLE_STARTED:
@@ -2350,7 +2501,8 @@ Dbdict::restartCreateTab(Signal* signal, Uint32 tableId,
if(file && !ERROR_INSERTED(6002)){
jam();
- c_readTableRecord.noOfPages = te->m_noOfPages;
+ c_readTableRecord.noOfPages =
+ DIV(te->m_info_words + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
c_readTableRecord.pageId = 0;
c_readTableRecord.m_callback.m_callbackData = createTabPtr.p->key;
c_readTableRecord.m_callback.m_callbackFunction =
@@ -2406,7 +2558,7 @@ Dbdict::restartCreateTab_readTableConf(Signal* signal,
c_readTableRecord.tableId,
parseRecord.errorCode);
progError(__LINE__,
- ERR_INVALID_CONFIG,
+ NDBD_EXIT_INVALID_CONFIG,
buf);
ndbrequire(parseRecord.errorCode == 0);
}
@@ -2643,6 +2795,10 @@ void Dbdict::execNODE_FAILREP(Signal* signal)
c_blockState = BS_NODE_FAILURE;
ok = true;
break;
+ case BS_NODE_RESTART:
+ jam();
+ ok = true;
+ break;
}
ndbrequire(ok);
@@ -2665,6 +2821,15 @@ void Dbdict::execNODE_FAILREP(Signal* signal)
}//if
}//for
+ /*
+ * NODE_FAILREP guarantees that no "in flight" signal from
+ * a dead node is accepted, and also that the job buffer contains
+ * no such (un-executed) signals. Therefore no DICT_UNLOCK_ORD
+ * from a dead node (leading to master crash) is possible after
+ * this clean-up removes the lock record.
+ */
+ removeStaleDictLocks(signal, theFailedNodes);
+
}//execNODE_FAILREP()
@@ -2733,6 +2898,12 @@ Dbdict::execCREATE_TABLE_REQ(Signal* signal){
break;
}
+ if (c_blockState == BS_NODE_RESTART){
+ jam();
+ parseRecord.errorCode = CreateTableRef::BusyWithNR;
+ break;
+ }
+
if (c_blockState != BS_IDLE){
jam();
parseRecord.errorCode = CreateTableRef::Busy;
@@ -2882,6 +3053,12 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal)
return;
}
+ if(c_blockState == BS_NODE_RESTART){
+ jam();
+ alterTableRef(signal, req, AlterTableRef::BusyWithNR);
+ return;
+ }
+
if(c_blockState != BS_IDLE){
jam();
alterTableRef(signal, req, AlterTableRef::Busy);
@@ -3256,8 +3433,8 @@ Dbdict::execALTER_TAB_REQ(Signal * signal)
tabEntry.m_tableType = tablePtr.p->tableType;
tabEntry.m_tableState = SchemaFile::ALTER_TABLE_COMMITTED;
tabEntry.m_gcp = gci;
- tabEntry.m_noOfPages =
- DIV(tabInfoPtr.sz + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ tabEntry.m_info_words = tabInfoPtr.sz;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
Callback callback;
callback.m_callbackData = senderData;
@@ -3788,9 +3965,8 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
/**
* Update table version
*/
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- SchemaFile::TableEntry * tabEntry = getTableEntry(pagePtr.p, tabPtr.i);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
tabPtr.p->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
@@ -4096,8 +4272,8 @@ Dbdict::createTab_prepare(Signal* signal, CreateTabReq * req){
tabEntry.m_tableType = tabPtr.p->tableType;
tabEntry.m_tableState = SchemaFile::ADD_STARTED;
tabEntry.m_gcp = gci;
- tabEntry.m_noOfPages =
- DIV(tabInfoPtr.sz + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ tabEntry.m_info_words = tabInfoPtr.sz;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
Callback callback;
callback.m_callbackData = createTabPtr.p->key;
@@ -4181,6 +4357,44 @@ Dbdict::createTab_dih(Signal* signal,
sendSignal(DBDIH_REF, GSN_DIADDTABREQ, signal,
DiAddTabReq::SignalLength, JBB);
+
+ /**
+ * Create KeyDescriptor
+ */
+ KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i);
+ new (desc) KeyDescriptor();
+
+ Uint32 key = 0;
+ Uint32 tAttr = tabPtr.p->firstAttribute;
+ while (tAttr != RNIL)
+ {
+ jam();
+ AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
+ if (aRec->tupleKey)
+ {
+ desc->noOfKeyAttr ++;
+ desc->keyAttr[key].attributeDescriptor = aRec->attributeDescriptor;
+
+ Uint32 csNumber = (aRec->extPrecision >> 16);
+ if(csNumber)
+ {
+ desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
+ ndbrequire(all_charsets[csNumber]);
+ desc->hasCharAttr = 1;
+ }
+ else
+ {
+ desc->keyAttr[key].charsetInfo = 0;
+ }
+ if(AttributeDescriptor::getDKey(aRec->attributeDescriptor))
+ {
+ desc->noOfDistrKeys ++;
+ }
+ key++;
+ }
+ tAttr = aRec->nextAttrInTable;
+ }
+ ndbrequire(key == tabPtr.p->noOfPrimkey);
}
static
@@ -4249,6 +4463,13 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
Uint32 lhPageBits = 0;
::calcLHbits(&lhPageBits, &lhDistrBits, fragId, fragCount);
+ Uint64 maxRows = tabPtr.p->maxRowsLow +
+ (((Uint64)tabPtr.p->maxRowsHigh) << 32);
+ Uint64 minRows = tabPtr.p->minRowsLow +
+ (((Uint64)tabPtr.p->minRowsHigh) << 32);
+ maxRows = (maxRows + fragCount - 1) / fragCount;
+ minRows = (minRows + fragCount - 1) / fragCount;
+
{
LqhFragReq* req = (LqhFragReq*)signal->getDataPtrSend();
req->senderData = senderData;
@@ -4260,20 +4481,22 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
req->maxLoadFactor = tabPtr.p->maxLoadFactor;
req->minLoadFactor = tabPtr.p->minLoadFactor;
req->kValue = tabPtr.p->kValue;
- req->lh3DistrBits = lhDistrBits;
- req->lh3PageBits = lhPageBits;
+ req->lh3DistrBits = 0; //lhDistrBits;
+ req->lh3PageBits = 0; //lhPageBits;
req->noOfAttributes = tabPtr.p->noOfAttributes;
- req->noOfNullAttributes = tabPtr.p->noOfNullAttr;
- req->noOfPagesToPreAllocate = 0;
+ req->noOfNullAttributes = tabPtr.p->noOfNullBits;
+ req->maxRowsLow = maxRows & 0xFFFFFFFF;
+ req->maxRowsHigh = maxRows >> 32;
+ req->minRowsLow = minRows & 0xFFFFFFFF;
+ req->minRowsHigh = minRows >> 32;
req->schemaVersion = tabPtr.p->tableVersion;
Uint32 keyLen = tabPtr.p->tupKeyLength;
- req->keyLength = keyLen > 8 ? 0 : keyLen; // Put this into ACC instead
+ req->keyLength = keyLen; // wl-2066 no more "long keys"
req->nextLCP = lcpNo;
req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
req->noOfNewAttr = 0;
- // noOfCharsets passed to TUP in upper half
- req->noOfNewAttr |= (tabPtr.p->noOfCharsets << 16);
+ req->noOfCharsets = tabPtr.p->noOfCharsets;
req->checksumIndicator = 1;
req->noOfAttributeGroups = 1;
req->GCPIndicator = 0;
@@ -4334,7 +4557,7 @@ Dbdict::sendLQHADDATTRREQ(Signal* signal,
LqhAddAttrReq::Entry& entry = req->attributes[i];
entry.attrId = attrPtr.p->attributeId;
entry.attrDescriptor = attrPtr.p->attributeDescriptor;
- entry.extTypeInfo = attrPtr.p->extType;
+ entry.extTypeInfo = 0;
// charset number passed to TUP, TUX in upper half
entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
if (tabPtr.p->isIndex()) {
@@ -4476,10 +4699,12 @@ Dbdict::execTAB_COMMITCONF(Signal* signal){
signal->theData[3] = reference();
signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key;
- sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 6, JBB);
+ signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
+
+ sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
return;
}
-
+
ndbrequire(false);
}
@@ -4532,8 +4757,8 @@ Dbdict::createTab_commit(Signal * signal, CreateTabReq * req){
tabEntry.m_tableType = tabPtr.p->tableType;
tabEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
tabEntry.m_gcp = tabPtr.p->gciTableCreated;
- tabEntry.m_noOfPages =
- DIV(tabPtr.p->packedSize + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
+ tabEntry.m_info_words = tabPtr.p->packedSize;
+ memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
Callback callback;
callback.m_callbackData = createTabPtr.p->key;
@@ -4634,10 +4859,9 @@ Dbdict::createTab_dropComplete(Signal* signal,
c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
releaseTableObject(tabPtr.i);
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tabPtr.i);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tabPtr.i);
tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
//@todo check error
@@ -4835,10 +5059,18 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
tablePtr.p->minLoadFactor = tableDesc.MinLoadFactor;
tablePtr.p->maxLoadFactor = tableDesc.MaxLoadFactor;
tablePtr.p->fragmentType = (DictTabInfo::FragmentType)tableDesc.FragmentType;
- 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->maxRowsLow = tableDesc.MaxRowsLow;
+ tablePtr.p->maxRowsHigh = tableDesc.MaxRowsHigh;
+ tablePtr.p->minRowsLow = tableDesc.MinRowsLow;
+ tablePtr.p->minRowsHigh = tableDesc.MinRowsHigh;
+
+ Uint64 maxRows =
+ (((Uint64)tablePtr.p->maxRowsHigh) << 32) + tablePtr.p->maxRowsLow;
+ Uint64 minRows =
+ (((Uint64)tablePtr.p->minRowsHigh) << 32) + tablePtr.p->minRowsLow;
tablePtr.p->frmLen = tableDesc.FrmLen;
memcpy(tablePtr.p->frmData, tableDesc.FrmData, tableDesc.FrmLen);
@@ -4884,6 +5116,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
Uint32 keyLength = 0;
Uint32 attrCount = tablePtr.p->noOfAttributes;
Uint32 nullCount = 0;
+ Uint32 nullBits = 0;
Uint32 noOfCharsets = 0;
Uint16 charsets[128];
Uint32 recordLength = 0;
@@ -4936,19 +5169,24 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
attrPtr.p->attributeId = attrDesc.AttributeId;
attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
- attrPtr.p->extType = attrDesc.AttributeExtType;
attrPtr.p->extPrecision = attrDesc.AttributeExtPrecision;
attrPtr.p->extScale = attrDesc.AttributeExtScale;
attrPtr.p->extLength = attrDesc.AttributeExtLength;
// charset in upper half of precision
unsigned csNumber = (attrPtr.p->extPrecision >> 16);
if (csNumber != 0) {
+ /*
+ * A new charset is first accessed here on this node.
+ * TODO use separate thread (e.g. via NDBFS) if need to load from file
+ */
CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
if (cs == NULL) {
parseP->errorCode = CreateTableRef::InvalidCharset;
parseP->errorLine = __LINE__;
return;
}
+ // XXX should be done somewhere in mysql
+ all_charsets[cs->number] = cs;
unsigned i = 0;
while (i < noOfCharsets) {
if (charsets[i] == csNumber)
@@ -4966,9 +5204,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
}
}
- /**
- * Ignore incoming old-style type and recompute it.
- */
+ // compute attribute size and array size
bool translateOk = attrDesc.translateExtType();
tabRequire(translateOk, CreateTableRef::Inconsistency);
@@ -4981,15 +5217,12 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
}
Uint32 desc = 0;
- AttributeDescriptor::setType(desc, attrDesc.AttributeType);
+ AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
AttributeDescriptor::setArray(desc, attrDesc.AttributeArraySize);
AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
- AttributeDescriptor::setDGroup(desc, attrDesc.AttributeDGroup);
AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
-
- AttributeDescriptor::setStoredInTup(desc, attrDesc.AttributeStoredInd);
attrPtr.p->attributeDescriptor = desc;
attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
strcpy(attrPtr.p->defaultValue, attrDesc.AttributeDefaultValue);
@@ -5001,7 +5234,25 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
nullCount += attrDesc.AttributeNullableFlag;
const Uint32 aSz = (1 << attrDesc.AttributeSize);
- const Uint32 sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
+ Uint32 sz;
+ if(aSz != 1)
+ {
+ sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
+ }
+ else
+ {
+ sz = 0;
+ nullBits += attrDesc.AttributeArraySize;
+ }
+
+ if(attrDesc.AttributeArraySize == 0)
+ {
+ parseP->errorCode = CreateTableRef::InvalidArraySize;
+ parseP->status = status;
+ parseP->errorKey = it.getKey();
+ parseP->errorLine = __LINE__;
+ return;
+ }
recordLength += sz;
if(attrDesc.AttributeKeyFlag){
@@ -5030,6 +5281,7 @@ void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
tablePtr.p->noOfNullAttr = nullCount;
tablePtr.p->noOfCharsets = noOfCharsets;
tablePtr.p->tupKeyLength = keyLength;
+ tablePtr.p->noOfNullBits = nullCount + nullBits;
tabRequire(recordLength<= MAX_TUPLE_SIZE_IN_WORDS,
CreateTableRef::RecordTooBig);
@@ -5103,7 +5355,10 @@ void Dbdict::execWAIT_GCP_REF(Signal* signal)
/* ---------------------------------------------------------------- */
// Error Handling code needed
/* ---------------------------------------------------------------- */
- progError(ref->errorCode, 0);
+ char buf[32];
+ BaseString::snprintf(buf, sizeof(buf), "WAIT_GCP_REF ErrorCode=%d",
+ ref->errorCode);
+ progError(__LINE__, NDBD_EXIT_NDBREQUIRE, buf);
}//execWAIT_GCP_REF()
@@ -5134,6 +5389,12 @@ Dbdict::execDROP_TABLE_REQ(Signal* signal){
return;
}
+ if(c_blockState == BS_NODE_RESTART){
+ jam();
+ dropTableRef(signal, req, DropTableRef::BusyWithNR);
+ return;
+ }
+
if(c_blockState != BS_IDLE){
jam();
dropTableRef(signal, req, DropTableRef::Busy);
@@ -5492,21 +5753,22 @@ Dbdict::execPREP_DROP_TAB_REQ(Signal* signal){
/**
* Modify schema
*/
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tablePtr.i);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tablePtr.i);
SchemaFile::TableState tabState =
(SchemaFile::TableState)tableEntry->m_tableState;
ndbrequire(tabState == SchemaFile::TABLE_ADD_COMMITTED ||
tabState == SchemaFile::ALTER_TABLE_COMMITTED);
tableEntry->m_tableState = SchemaFile::DROP_TABLE_STARTED;
- computeChecksum((SchemaFile*)pagePtr.p);
+ computeChecksum(xsf, tablePtr.i / NDB_SF_PAGE_ENTRIES);
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.newFile = false;
+ c_writeSchemaRecord.firstPage = tablePtr.i / NDB_SF_PAGE_ENTRIES;
+ c_writeSchemaRecord.noOfPages = 1;
c_writeSchemaRecord.m_callback.m_callbackData = dropTabPtr.p->key;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::prepDropTab_writeSchemaConf);
@@ -5667,20 +5929,20 @@ Dbdict::dropTab_complete(Signal* signal,
/**
* Write to schema file
*/
- PageRecordPtr pagePtr;
- c_pageRecordArray.getPtr(pagePtr, c_schemaRecord.schemaPage);
-
- SchemaFile::TableEntry * tableEntry = getTableEntry(pagePtr.p, tableId);
+ XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
+ SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
SchemaFile::TableState tabState =
(SchemaFile::TableState)tableEntry->m_tableState;
ndbrequire(tabState == SchemaFile::DROP_TABLE_STARTED);
tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
- computeChecksum((SchemaFile*)pagePtr.p);
+ computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
ndbrequire(c_writeSchemaRecord.inUse == false);
c_writeSchemaRecord.inUse = true;
c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
+ c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
+ c_writeSchemaRecord.noOfPages = 1;
c_writeSchemaRecord.m_callback.m_callbackData = dropTabPtr.p->key;
c_writeSchemaRecord.m_callback.m_callbackFunction =
safe_cast(&Dbdict::dropTab_writeSchemaConf);
@@ -5864,7 +6126,10 @@ void Dbdict::sendGET_TABLEID_REF(Signal* signal,
void Dbdict::execGET_TABINFOREQ(Signal* signal)
{
jamEntry();
- if(!assembleFragments(signal)) { return; }
+ if(!assembleFragments(signal))
+ {
+ return;
+ }
GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
@@ -6449,11 +6714,15 @@ void
Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr)
{
jam();
+ if (ERROR_INSERTED(6006) && ! opPtr.p->m_isMaster) {
+ ndbrequire(false);
+ }
}
void
Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
{
+ Uint32 attrid_map[MAX_ATTRIBUTES_IN_INDEX];
Uint32 k;
jam();
const CreateIndxReq* const req = &opPtr.p->m_request;
@@ -6523,39 +6792,49 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
// tree node size in words (make configurable later)
indexPtr.p->tupKeyLength = MAX_TTREE_NODE_SIZE;
}
- // hash index attributes must currently be in table order
- Uint32 prevAttrId = RNIL;
+
+ AttributeMask mask;
+ mask.clear();
for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
jam();
- bool found = false;
- for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
- AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
- tAttr = aRec->nextAttrInTable;
- if (aRec->attributeId != opPtr.p->m_attrList.id[k])
+ unsigned current_id= opPtr.p->m_attrList.id[k];
+ AttributeRecord* aRec= NULL;
+ Uint32 tAttr= tablePtr.p->firstAttribute;
+ for (; tAttr != RNIL; tAttr= aRec->nextAttrInTable)
+ {
+ aRec = c_attributeRecordPool.getPtr(tAttr);
+ if (aRec->attributeId != current_id)
continue;
jam();
- found = true;
- const Uint32 a = aRec->attributeDescriptor;
- if (indexPtr.p->isHashIndex()) {
- const Uint32 s1 = AttributeDescriptor::getSize(a);
- const Uint32 s2 = AttributeDescriptor::getArraySize(a);
- indexPtr.p->tupKeyLength += ((1 << s1) * s2 + 31) >> 5;
- }
+ break;
}
- if (! found) {
+ if (tAttr == RNIL) {
jam();
opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
opPtr.p->m_errorLine = __LINE__;
return;
}
- if (indexPtr.p->isHashIndex() &&
- k > 0 && prevAttrId >= opPtr.p->m_attrList.id[k]) {
+ if (mask.get(current_id))
+ {
jam();
- opPtr.p->m_errorCode = CreateIndxRef::InvalidAttributeOrder;
+ opPtr.p->m_errorCode = CreateIndxRef::DuplicateAttributes;
opPtr.p->m_errorLine = __LINE__;
return;
}
- prevAttrId = opPtr.p->m_attrList.id[k];
+ mask.set(current_id);
+
+ const Uint32 a = aRec->attributeDescriptor;
+ unsigned kk= k;
+ if (indexPtr.p->isHashIndex()) {
+ const Uint32 s1 = AttributeDescriptor::getSize(a);
+ const Uint32 s2 = AttributeDescriptor::getArraySize(a);
+ indexPtr.p->tupKeyLength += ((1 << s1) * s2 + 31) >> 5;
+ // reorder the attributes according to the tableid order
+ // for unque indexes
+ for (; kk > 0 && current_id < attrid_map[kk-1]>>16; kk--)
+ attrid_map[kk]= attrid_map[kk-1];
+ }
+ attrid_map[kk]= k | (current_id << 16);
}
indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
// plus concatenated primary table key attribute
@@ -6576,15 +6855,21 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
AttributeRecordPtr aRecPtr;
c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute);
for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
+ // insert the attributes in the order decided above in attrid_map
+ // k is new order, current_id is in previous order
+ // ToDo: make sure "current_id" is stored with the table and
+ // passed up to NdbDictionary
+ unsigned current_id= opPtr.p->m_attrList.id[attrid_map[k] & 0xffff];
jam();
for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
tAttr = aRec->nextAttrInTable;
- if (aRec->attributeId != opPtr.p->m_attrList.id[k])
+ if (aRec->attributeId != current_id)
continue;
jam();
const Uint32 a = aRec->attributeDescriptor;
bool isNullable = AttributeDescriptor::getNullable(a);
+ Uint32 attrType = AttributeDescriptor::getType(a);
w.add(DictTabInfo::AttributeName, aRec->attributeName);
w.add(DictTabInfo::AttributeId, k);
if (indexPtr.p->isHashIndex()) {
@@ -6595,9 +6880,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
}
- w.add(DictTabInfo::AttributeStoredInd, (Uint32)DictTabInfo::Stored);
- // ext type overrides
- w.add(DictTabInfo::AttributeExtType, aRec->extType);
+ w.add(DictTabInfo::AttributeExtType, attrType);
w.add(DictTabInfo::AttributeExtPrecision, aRec->extPrecision);
w.add(DictTabInfo::AttributeExtScale, aRec->extScale);
w.add(DictTabInfo::AttributeExtLength, aRec->extLength);
@@ -6610,9 +6893,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::AttributeName, "NDB$PK");
w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
- w.add(DictTabInfo::AttributeStoredInd, (Uint32)DictTabInfo::Stored);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- // ext type overrides
w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
@@ -6623,9 +6904,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
w.add(DictTabInfo::AttributeName, "NDB$TNODE");
w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
- w.add(DictTabInfo::AttributeStoredInd, (Uint32)DictTabInfo::Stored);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
- // ext type overrides
w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
w.add(DictTabInfo::AttributeExtLength, indexPtr.p->tupKeyLength);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
@@ -7124,2171 +7403,6 @@ Dbdict::dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr,
sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
}
-/*****************************************************
- *
- * Util signalling
- *
- *****************************************************/
-
-int
-Dbdict::sendSignalUtilReq(Callback *pcallback,
- BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections)
-{
- jam();
- EVENT_TRACE;
- OpSignalUtilPtr utilRecPtr;
-
- // Seize a Util Send record
- if (!c_opSignalUtil.seize(utilRecPtr)) {
- // Failed to allocate util record
- return -1;
- }
- utilRecPtr.p->m_callback = *pcallback;
-
- // should work for all util signal classes
- UtilPrepareReq *req = (UtilPrepareReq*)signal->getDataPtrSend();
- utilRecPtr.p->m_userData = req->getSenderData();
- req->setSenderData(utilRecPtr.i);
-
- if (ptr) {
- jam();
- sendSignal(ref, gsn, signal, length, jbuf, ptr, noOfSections);
- } else {
- jam();
- sendSignal(ref, gsn, signal, length, jbuf);
- }
-
- return 0;
-}
-
-int
-Dbdict::recvSignalUtilReq(Signal* signal, Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- UtilPrepareConf * const req = (UtilPrepareConf*)signal->getDataPtr();
- OpSignalUtilPtr utilRecPtr;
- utilRecPtr.i = req->getSenderData();
- if ((utilRecPtr.p = c_opSignalUtil.getPtr(utilRecPtr.i)) == NULL) {
- jam();
- return -1;
- }
-
- req->setSenderData(utilRecPtr.p->m_userData);
- Callback c = utilRecPtr.p->m_callback;
- c_opSignalUtil.release(utilRecPtr);
-
- execute(signal, c, returnCode);
- return 0;
-}
-
-void Dbdict::execUTIL_PREPARE_CONF(Signal *signal)
-{
- jamEntry();
- EVENT_TRACE;
- ndbrequire(recvSignalUtilReq(signal, 0) == 0);
-}
-
-void
-Dbdict::execUTIL_PREPARE_REF(Signal *signal)
-{
- jamEntry();
- EVENT_TRACE;
- ndbrequire(recvSignalUtilReq(signal, 1) == 0);
-}
-
-void Dbdict::execUTIL_EXECUTE_CONF(Signal *signal)
-{
- jamEntry();
- EVENT_TRACE;
- ndbrequire(recvSignalUtilReq(signal, 0) == 0);
-}
-
-void Dbdict::execUTIL_EXECUTE_REF(Signal *signal)
-{
- jamEntry();
- EVENT_TRACE;
-
-#ifdef EVENT_DEBUG
- UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend();
-
- ndbout_c("execUTIL_EXECUTE_REF");
- ndbout_c("senderData %u",ref->getSenderData());
- ndbout_c("errorCode %u",ref->getErrorCode());
- ndbout_c("TCErrorCode %u",ref->getTCErrorCode());
-#endif
-
- ndbrequire(recvSignalUtilReq(signal, 1) == 0);
-}
-void Dbdict::execUTIL_RELEASE_CONF(Signal *signal)
-{
- jamEntry();
- EVENT_TRACE;
- ndbrequire(false);
- ndbrequire(recvSignalUtilReq(signal, 0) == 0);
-}
-void Dbdict::execUTIL_RELEASE_REF(Signal *signal)
-{
- jamEntry();
- EVENT_TRACE;
- ndbrequire(false);
- ndbrequire(recvSignalUtilReq(signal, 1) == 0);
-}
-
-/**
- * MODULE: Create event
- *
- * Create event in DICT.
- *
- *
- * Request type in CREATE_EVNT signals:
- *
- * Signalflow see Dbdict.txt
- *
- */
-
-/*****************************************************************
- *
- * Systable stuff
- *
- */
-
-const Uint32 Dbdict::sysTab_NDBEVENTS_0_szs[EVENT_SYSTEM_TABLE_LENGTH] = {
- sizeof(((sysTab_NDBEVENTS_0*)0)->NAME),
- sizeof(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE),
- sizeof(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME),
- sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK),
- sizeof(((sysTab_NDBEVENTS_0*)0)->SUBID),
- sizeof(((sysTab_NDBEVENTS_0*)0)->SUBKEY)
-};
-
-void
-Dbdict::prepareTransactionEventSysTable (Callback *pcallback,
- Signal* signal,
- Uint32 senderData,
- UtilPrepareReq::OperationTypeValue prepReq)
-{
- // find table id for event system table
- TableRecord keyRecord;
- strcpy(keyRecord.tableName, EVENT_SYSTEM_TABLE_NAME);
-
- TableRecordPtr tablePtr;
- c_tableRecordHash.find(tablePtr, keyRecord);
-
- ndbrequire(tablePtr.i != RNIL); // system table must exist
-
- Uint32 tableId = tablePtr.p->tableId; /* System table */
- Uint32 noAttr = tablePtr.p->noOfAttributes;
- ndbrequire(noAttr == EVENT_SYSTEM_TABLE_LENGTH);
-
- switch (prepReq) {
- case UtilPrepareReq::Update:
- case UtilPrepareReq::Insert:
- case UtilPrepareReq::Write:
- case UtilPrepareReq::Read:
- jam();
- break;
- case UtilPrepareReq::Delete:
- jam();
- noAttr = 1; // only involves Primary key which should be the first
- break;
- }
- prepareUtilTransaction(pcallback, signal, senderData, tableId, NULL,
- prepReq, noAttr, NULL, NULL);
-}
-
-void
-Dbdict::prepareUtilTransaction(Callback *pcallback,
- Signal* signal,
- Uint32 senderData,
- Uint32 tableId,
- const char* tableName,
- UtilPrepareReq::OperationTypeValue prepReq,
- Uint32 noAttr,
- Uint32 attrIds[],
- const char *attrNames[])
-{
- jam();
- EVENT_TRACE;
-
- UtilPrepareReq * utilPrepareReq =
- (UtilPrepareReq *)signal->getDataPtrSend();
-
- utilPrepareReq->setSenderRef(reference());
- utilPrepareReq->setSenderData(senderData);
-
- const Uint32 pageSizeInWords = 128;
- Uint32 propPage[pageSizeInWords];
- LinearWriter w(&propPage[0],128);
- w.first();
- w.add(UtilPrepareReq::NoOfOperations, 1);
- w.add(UtilPrepareReq::OperationType, prepReq);
- if (tableName) {
- jam();
- w.add(UtilPrepareReq::TableName, tableName);
- } else {
- jam();
- w.add(UtilPrepareReq::TableId, tableId);
- }
- for(Uint32 i = 0; i < noAttr; i++)
- if (tableName) {
- jam();
- w.add(UtilPrepareReq::AttributeName, attrNames[i]);
- } else {
- if (attrIds) {
- jam();
- w.add(UtilPrepareReq::AttributeId, attrIds[i]);
- } else {
- jam();
- w.add(UtilPrepareReq::AttributeId, i);
- }
- }
-#ifdef EVENT_DEBUG
- // Debugging
- SimplePropertiesLinearReader reader(propPage, w.getWordsUsed());
- printf("Dict::prepareInsertTransactions: Sent SimpleProperties:\n");
- reader.printAll(ndbout);
-#endif
-
- struct LinearSectionPtr sectionsPtr[UtilPrepareReq::NoOfSections];
- sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].p = propPage;
- sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].sz = w.getWordsUsed();
-
- sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_PREPARE_REQ, signal,
- UtilPrepareReq::SignalLength, JBB,
- sectionsPtr, UtilPrepareReq::NoOfSections);
-}
-
-/*****************************************************************
- *
- * CREATE_EVNT_REQ has three types RT_CREATE, RT_GET (from user)
- * and RT_DICT_AFTER_GET send from master DICT to slaves
- *
- * This function just dscpaches these to
- *
- * createEvent_RT_USER_CREATE
- * createEvent_RT_USER_GET
- * createEvent_RT_DICT_AFTER_GET
- *
- * repectively
- *
- */
-
-void
-Dbdict::execCREATE_EVNT_REQ(Signal* signal)
-{
- jamEntry();
-
-#if 0
- {
- SafeCounterHandle handle;
- {
- SafeCounter tmp(c_counterMgr, handle);
- tmp.init<CreateEvntRef>(CMVMI, GSN_DUMP_STATE_ORD, /* senderData */ 13);
- tmp.clearWaitingFor();
- tmp.setWaitingFor(3);
- ndbrequire(!tmp.done());
- ndbout_c("Allocted");
- }
- ndbrequire(!handle.done());
- {
- SafeCounter tmp(c_counterMgr, handle);
- tmp.clearWaitingFor(3);
- ndbrequire(tmp.done());
- ndbout_c("Deallocted");
- }
- ndbrequire(handle.done());
- }
- {
- NodeBitmask nodes;
- nodes.clear();
-
- nodes.set(2);
- nodes.set(3);
- nodes.set(4);
- nodes.set(5);
-
- {
- Uint32 i = 0;
- while((i = nodes.find(i)) != NodeBitmask::NotFound){
- ndbout_c("1 Node id = %u", i);
- i++;
- }
- }
-
- NodeReceiverGroup rg(DBDICT, nodes);
- RequestTracker rt2;
- ndbrequire(rt2.done());
- ndbrequire(!rt2.hasRef());
- ndbrequire(!rt2.hasConf());
- rt2.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13);
-
- RequestTracker rt3;
- rt3.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13);
-
- ndbrequire(!rt2.done());
- ndbrequire(!rt3.done());
-
- rt2.reportRef(c_counterMgr, 2);
- rt3.reportConf(c_counterMgr, 2);
-
- ndbrequire(!rt2.done());
- ndbrequire(!rt3.done());
-
- rt2.reportConf(c_counterMgr, 3);
- rt3.reportConf(c_counterMgr, 3);
-
- ndbrequire(!rt2.done());
- ndbrequire(!rt3.done());
-
- rt2.reportConf(c_counterMgr, 4);
- rt3.reportConf(c_counterMgr, 4);
-
- ndbrequire(!rt2.done());
- ndbrequire(!rt3.done());
-
- rt2.reportConf(c_counterMgr, 5);
- rt3.reportConf(c_counterMgr, 5);
-
- ndbrequire(rt2.done());
- ndbrequire(rt3.done());
- }
-#endif
-
- if (! assembleFragments(signal)) {
- jam();
- return;
- }
-
- CreateEvntReq *req = (CreateEvntReq*)signal->getDataPtr();
- const CreateEvntReq::RequestType requestType = req->getRequestType();
- const Uint32 requestFlag = req->getRequestFlag();
-
- OpCreateEventPtr evntRecPtr;
- // Seize a Create Event record
- if (!c_opCreateEvent.seize(evntRecPtr)) {
- // Failed to allocate event record
- jam();
- releaseSections(signal);
-
- CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
- ret->senderRef = reference();
- ret->setErrorCode(CreateEvntRef::SeizeError);
- ret->setErrorLine(__LINE__);
- ret->setErrorNode(reference());
- sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
- CreateEvntRef::SignalLength, JBB);
- return;
- }
-
-#ifdef EVENT_DEBUG
- ndbout_c("DBDICT::execCREATE_EVNT_REQ from %u evntRecId = (%d)", refToNode(signal->getSendersBlockRef()), evntRecPtr.i);
-#endif
-
- ndbrequire(req->getUserRef() == signal->getSendersBlockRef());
-
- evntRecPtr.p->init(req,this);
-
- if (requestFlag & (Uint32)CreateEvntReq::RT_DICT_AFTER_GET) {
- jam();
- EVENT_TRACE;
- createEvent_RT_DICT_AFTER_GET(signal, evntRecPtr);
- return;
- }
- if (requestType == CreateEvntReq::RT_USER_GET) {
- jam();
- EVENT_TRACE;
- createEvent_RT_USER_GET(signal, evntRecPtr);
- return;
- }
- if (requestType == CreateEvntReq::RT_USER_CREATE) {
- jam();
- EVENT_TRACE;
- createEvent_RT_USER_CREATE(signal, evntRecPtr);
- return;
- }
-
-#ifdef EVENT_DEBUG
- ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ other" << endl;
-#endif
- jam();
- releaseSections(signal);
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-/********************************************************************
- *
- * Event creation
- *
- *****************************************************************/
-
-void
-Dbdict::createEvent_RT_USER_CREATE(Signal* signal, OpCreateEventPtr evntRecPtr){
- jam();
- evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
-
-#ifdef EVENT_DEBUG
- ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ RT_USER" << endl;
- char buf[128] = {0};
- AttributeMask mask = evntRecPtr.p->m_request.getAttrListBitmask();
- mask.getText(buf);
- ndbout_c("mask = %s", buf);
-#endif
-
- // Interpret the long signal
-
- SegmentedSectionPtr ssPtr;
- // save name and event properties
- signal->getSection(ssPtr, CreateEvntReq::EVENT_NAME_SECTION);
-
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
-#ifdef EVENT_DEBUG
- r0.printAll(ndbout);
-#endif
- // event name
- if ((!r0.first()) ||
- (r0.getValueType() != SimpleProperties::StringValue) ||
- (r0.getValueLen() <= 0)) {
- jam();
- releaseSections(signal);
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
- r0.getString(evntRecPtr.p->m_eventRec.NAME);
- {
- int len = strlen(evntRecPtr.p->m_eventRec.NAME);
- memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
-#ifdef EVENT_DEBUG
- printf("CreateEvntReq::RT_USER_CREATE; EventName %s, len %u\n",
- evntRecPtr.p->m_eventRec.NAME, len);
- for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
- printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
- printf("\n");
-#endif
- }
- // table name
- if ((!r0.next()) ||
- (r0.getValueType() != SimpleProperties::StringValue) ||
- (r0.getValueLen() <= 0)) {
- jam();
- releaseSections(signal);
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
- r0.getString(evntRecPtr.p->m_eventRec.TABLE_NAME);
- {
- int len = strlen(evntRecPtr.p->m_eventRec.TABLE_NAME);
- memset(evntRecPtr.p->m_eventRec.TABLE_NAME+len, 0, MAX_TAB_NAME_SIZE-len);
- }
-
-#ifdef EVENT_DEBUG
- ndbout_c("event name: %s",evntRecPtr.p->m_eventRec.NAME);
- ndbout_c("table name: %s",evntRecPtr.p->m_eventRec.TABLE_NAME);
-#endif
-
- releaseSections(signal);
-
- // Send request to SUMA
-
- CreateSubscriptionIdReq * sumaIdReq =
- (CreateSubscriptionIdReq *)signal->getDataPtrSend();
-
- // make sure we save the original sender for later
- sumaIdReq->senderData = evntRecPtr.i;
-#ifdef EVENT_DEBUG
- ndbout << "sumaIdReq->senderData = " << sumaIdReq->senderData << endl;
-#endif
- sendSignal(SUMA_REF, GSN_CREATE_SUBID_REQ, signal,
- CreateSubscriptionIdReq::SignalLength, JBB);
- // we should now return in either execCREATE_SUBID_CONF
- // or execCREATE_SUBID_REF
-}
-
-void Dbdict::execCREATE_SUBID_REF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
- CreateSubscriptionIdRef * const ref =
- (CreateSubscriptionIdRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = ref->senderData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-void Dbdict::execCREATE_SUBID_CONF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
-
- CreateSubscriptionIdConf const * sumaIdConf =
- (CreateSubscriptionIdConf *)signal->getDataPtr();
-
- Uint32 evntRecId = sumaIdConf->senderData;
- OpCreateEvent *evntRec;
-
- ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL);
-
- evntRec->m_request.setEventId(sumaIdConf->subscriptionId);
- evntRec->m_request.setEventKey(sumaIdConf->subscriptionKey);
-
- releaseSections(signal);
-
- Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
-
- prepareTransactionEventSysTable(&c, signal, evntRecId,
- UtilPrepareReq::Insert);
-}
-
-void
-Dbdict::createEventComplete_RT_USER_CREATE(Signal* signal,
- OpCreateEventPtr evntRecPtr){
- jam();
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-/*********************************************************************
- *
- * UTIL_PREPARE, UTIL_EXECUTE
- *
- * insert or read systable NDB$EVENTS_0
- */
-
-void interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode,
- bool& temporary, Uint32& line)
-{
- switch (errorCode) {
- case UtilPrepareRef::NO_ERROR:
- jam();
- line = __LINE__;
- EVENT_TRACE;
- break;
- case UtilPrepareRef::PREPARE_SEIZE_ERROR:
- jam();
- temporary = true;
- line = __LINE__;
- EVENT_TRACE;
- break;
- case UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR:
- jam();
- line = __LINE__;
- EVENT_TRACE;
- break;
- case UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR:
- jam();
- line = __LINE__;
- EVENT_TRACE;
- break;
- case UtilPrepareRef::DICT_TAB_INFO_ERROR:
- jam();
- line = __LINE__;
- EVENT_TRACE;
- break;
- case UtilPrepareRef::MISSING_PROPERTIES_SECTION:
- jam();
- line = __LINE__;
- EVENT_TRACE;
- break;
- default:
- jam();
- line = __LINE__;
- EVENT_TRACE;
- break;
- }
-}
-
-void
-Dbdict::createEventUTIL_PREPARE(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- if (returnCode == 0) {
- UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
- jam();
- evntRecPtr.i = req->getSenderData();
- const Uint32 prepareId = req->getPrepareId();
-
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- Callback c = { safe_cast(&Dbdict::createEventUTIL_EXECUTE), 0 };
-
- switch (evntRecPtr.p->m_requestType) {
- case CreateEvntReq::RT_USER_GET:
-#ifdef EVENT_DEBUG
- printf("get type = %d\n", CreateEvntReq::RT_USER_GET);
-#endif
- jam();
- executeTransEventSysTable(&c, signal,
- evntRecPtr.i, evntRecPtr.p->m_eventRec,
- prepareId, UtilPrepareReq::Read);
- break;
- case CreateEvntReq::RT_USER_CREATE:
-#ifdef EVENT_DEBUG
- printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
-#endif
- {
- evntRecPtr.p->m_eventRec.EVENT_TYPE = evntRecPtr.p->m_request.getEventType();
- AttributeMask m = evntRecPtr.p->m_request.getAttrListBitmask();
- memcpy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK, &m,
- sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK));
- evntRecPtr.p->m_eventRec.SUBID = evntRecPtr.p->m_request.getEventId();
- evntRecPtr.p->m_eventRec.SUBKEY = evntRecPtr.p->m_request.getEventKey();
- }
- jam();
- executeTransEventSysTable(&c, signal,
- evntRecPtr.i, evntRecPtr.p->m_eventRec,
- prepareId, UtilPrepareReq::Insert);
- break;
- default:
-#ifdef EVENT_DEBUG
- printf("type = %d\n", evntRecPtr.p->m_requestType);
- printf("bet type = %d\n", CreateEvntReq::RT_USER_GET);
- printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
-#endif
- ndbrequire(false);
- }
- } else { // returnCode != 0
- UtilPrepareRef* const ref = (UtilPrepareRef*)signal->getDataPtr();
-
- const UtilPrepareRef::ErrorCode errorCode =
- (UtilPrepareRef::ErrorCode)ref->getErrorCode();
-
- OpCreateEventPtr evntRecPtr;
- evntRecPtr.i = ref->getSenderData();
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- bool temporary = false;
- interpretUtilPrepareErrorCode(errorCode,
- temporary, evntRecPtr.p->m_errorLine);
- if (temporary) {
- evntRecPtr.p->m_errorCode =
- CreateEvntRef::makeTemporary(CreateEvntRef::Undefined);
- }
-
- if (evntRecPtr.p->m_errorCode == 0) {
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- }
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- }
-}
-
-void Dbdict::executeTransEventSysTable(Callback *pcallback, Signal *signal,
- const Uint32 ptrI,
- sysTab_NDBEVENTS_0& m_eventRec,
- const Uint32 prepareId,
- UtilPrepareReq::OperationTypeValue prepReq)
-{
- jam();
- const Uint32 noAttr = EVENT_SYSTEM_TABLE_LENGTH;
- Uint32 total_len = 0;
-
- Uint32* attrHdr = signal->theData + 25;
- Uint32* attrPtr = attrHdr;
-
- Uint32 id=0;
- // attribute 0 event name: Primary Key
- {
- AttributeHeader::init(attrPtr, id, sysTab_NDBEVENTS_0_szs[id]/4);
- total_len += sysTab_NDBEVENTS_0_szs[id];
- attrPtr++; id++;
- }
-
- switch (prepReq) {
- case UtilPrepareReq::Read:
- jam();
- EVENT_TRACE;
- // no more
- while ( id < noAttr )
- AttributeHeader::init(attrPtr++, id++, 0);
- ndbrequire(id == (Uint32) noAttr);
- break;
- case UtilPrepareReq::Insert:
- jam();
- EVENT_TRACE;
- while ( id < noAttr ) {
- AttributeHeader::init(attrPtr, id, sysTab_NDBEVENTS_0_szs[id]/4);
- total_len += sysTab_NDBEVENTS_0_szs[id];
- attrPtr++; id++;
- }
- ndbrequire(id == (Uint32) noAttr);
- break;
- case UtilPrepareReq::Delete:
- ndbrequire(id == 1);
- break;
- default:
- ndbrequire(false);
- }
-
- LinearSectionPtr headerPtr;
- LinearSectionPtr dataPtr;
-
- headerPtr.p = attrHdr;
- headerPtr.sz = noAttr;
-
- dataPtr.p = (Uint32*)&m_eventRec;
- dataPtr.sz = total_len/4;
-
- ndbrequire((total_len == sysTab_NDBEVENTS_0_szs[0]) ||
- (total_len == sizeof(sysTab_NDBEVENTS_0)));
-
-#if 0
- printf("Header size %u\n", headerPtr.sz);
- for(int i = 0; i < (int)headerPtr.sz; i++)
- printf("H'%.8x ", attrHdr[i]);
- printf("\n");
-
- printf("Data size %u\n", dataPtr.sz);
- for(int i = 0; i < (int)dataPtr.sz; i++)
- printf("H'%.8x ", dataPage[i]);
- printf("\n");
-#endif
-
- executeTransaction(pcallback, signal,
- ptrI,
- prepareId,
- id,
- headerPtr,
- dataPtr);
-}
-
-void Dbdict::executeTransaction(Callback *pcallback,
- Signal* signal,
- Uint32 senderData,
- Uint32 prepareId,
- Uint32 noAttr,
- LinearSectionPtr headerPtr,
- LinearSectionPtr dataPtr)
-{
- jam();
- EVENT_TRACE;
-
- UtilExecuteReq * utilExecuteReq =
- (UtilExecuteReq *)signal->getDataPtrSend();
-
- utilExecuteReq->setSenderRef(reference());
- utilExecuteReq->setSenderData(senderData);
- utilExecuteReq->setPrepareId(prepareId);
- utilExecuteReq->setReleaseFlag(); // must be done after setting prepareId
-
-#if 0
- printf("Header size %u\n", headerPtr.sz);
- for(int i = 0; i < (int)headerPtr.sz; i++)
- printf("H'%.8x ", headerBuffer[i]);
- printf("\n");
-
- printf("Data size %u\n", dataPtr.sz);
- for(int i = 0; i < (int)dataPtr.sz; i++)
- printf("H'%.8x ", dataBuffer[i]);
- printf("\n");
-#endif
-
- struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
- sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = headerPtr.p;
- sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr;
- sectionsPtr[UtilExecuteReq::DATA_SECTION].p = dataPtr.p;
- sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataPtr.sz;
-
- sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal,
- UtilExecuteReq::SignalLength, JBB,
- sectionsPtr, UtilExecuteReq::NoOfSections);
-}
-
-void Dbdict::parseReadEventSys(Signal* signal, sysTab_NDBEVENTS_0& m_eventRec)
-{
- SegmentedSectionPtr headerPtr, dataPtr;
- jam();
- signal->getSection(headerPtr, UtilExecuteReq::HEADER_SECTION);
- SectionReader headerReader(headerPtr, getSectionSegmentPool());
-
- signal->getSection(dataPtr, UtilExecuteReq::DATA_SECTION);
- SectionReader dataReader(dataPtr, getSectionSegmentPool());
-
- AttributeHeader header;
- Uint32 *dst = (Uint32*)&m_eventRec;
-
- for (int i = 0; i < EVENT_SYSTEM_TABLE_LENGTH; i++) {
- headerReader.getWord((Uint32 *)&header);
- int sz = header.getDataSize();
- for (int i=0; i < sz; i++)
- dataReader.getWord(dst++);
- }
-
- ndbrequire( ((char*)dst-(char*)&m_eventRec) == sizeof(m_eventRec) );
-
- releaseSections(signal);
-}
-
-void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- if (returnCode == 0) {
- // Entry into system table all set
- UtilExecuteConf* const conf = (UtilExecuteConf*)signal->getDataPtr();
- jam();
- OpCreateEventPtr evntRecPtr;
- evntRecPtr.i = conf->getSenderData();
-
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
- OpCreateEvent *evntRec = evntRecPtr.p;
-
- switch (evntRec->m_requestType) {
- case CreateEvntReq::RT_USER_GET: {
-#ifdef EVENT_DEBUG
- printf("get type = %d\n", CreateEvntReq::RT_USER_GET);
-#endif
- parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
-
- evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE);
- evntRec->m_request.setAttrListBitmask(*(AttributeMask*)evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
- evntRec->m_request.setEventId(evntRecPtr.p->m_eventRec.SUBID);
- evntRec->m_request.setEventKey(evntRecPtr.p->m_eventRec.SUBKEY);
-
-#ifdef EVENT_DEBUG
- printf("EventName: %s\n", evntRec->m_eventRec.NAME);
- printf("TableName: %s\n", evntRec->m_eventRec.TABLE_NAME);
-#endif
-
- // find table id for event table
- TableRecord keyRecord;
- strcpy(keyRecord.tableName, evntRecPtr.p->m_eventRec.TABLE_NAME);
-
- TableRecordPtr tablePtr;
- c_tableRecordHash.find(tablePtr, keyRecord);
-
- if (tablePtr.i == RNIL) {
- jam();
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
- evntRec->m_request.setTableId(tablePtr.p->tableId);
-
- createEventComplete_RT_USER_GET(signal, evntRecPtr);
- return;
- }
- case CreateEvntReq::RT_USER_CREATE: {
-#ifdef EVENT_DEBUG
- printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
-#endif
- jam();
- createEventComplete_RT_USER_CREATE(signal, evntRecPtr);
- return;
- }
- break;
- default:
- ndbrequire(false);
- }
- } else { // returnCode != 0
- UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
- evntRecPtr.i = ref->getSenderData();
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
- jam();
- evntRecPtr.p->m_errorNode = reference();
- evntRecPtr.p->m_errorLine = __LINE__;
-
- switch (ref->getErrorCode()) {
- case UtilExecuteRef::TCError:
- switch (ref->getTCErrorCode()) {
- case ZNOT_FOUND:
- jam();
- evntRecPtr.p->m_errorCode = CreateEvntRef::EventNotFound;
- break;
- case ZALREADYEXIST:
- jam();
- evntRecPtr.p->m_errorCode = CreateEvntRef::EventExists;
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = CreateEvntRef::UndefinedTCError;
- break;
- }
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- break;
- }
-
- createEvent_sendReply(signal, evntRecPtr);
- }
-}
-
-/***********************************************************************
- *
- * NdbEventOperation, reading systable, creating event in suma
- *
- */
-
-void
-Dbdict::createEvent_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
- jam();
- EVENT_TRACE;
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REQ::RT_USER_GET evntRecPtr.i = (%d), ref = %u", evntRecPtr.i, evntRecPtr.p->m_request.getUserRef());
-#endif
-
- SegmentedSectionPtr ssPtr;
-
- signal->getSection(ssPtr, 0);
-
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
-#ifdef EVENT_DEBUG
- r0.printAll(ndbout);
-#endif
- if ((!r0.first()) ||
- (r0.getValueType() != SimpleProperties::StringValue) ||
- (r0.getValueLen() <= 0)) {
- jam();
- releaseSections(signal);
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
- r0.getString(evntRecPtr.p->m_eventRec.NAME);
- int len = strlen(evntRecPtr.p->m_eventRec.NAME);
- memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
-
- releaseSections(signal);
-
- Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
-
- prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
- UtilPrepareReq::Read);
- /*
- * Will read systable and fill an OpCreateEventPtr
- * and return below
- */
-}
-
-void
-Dbdict::createEventComplete_RT_USER_GET(Signal* signal,
- OpCreateEventPtr evntRecPtr){
- jam();
-
- // Send to oneself and the other DICT's
- CreateEvntReq * req = (CreateEvntReq *)signal->getDataPtrSend();
-
- *req = evntRecPtr.p->m_request;
- req->senderRef = reference();
- req->senderData = evntRecPtr.i;
-
- req->addRequestFlag(CreateEvntReq::RT_DICT_AFTER_GET);
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Coordinator) sending GSN_CREATE_EVNT_REQ::RT_DICT_AFTER_GET to DBDICT participants evntRecPtr.i = (%d)", evntRecPtr.i);
-#endif
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- RequestTracker & p = evntRecPtr.p->m_reqTracker;
- p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, evntRecPtr.i);
-
- sendSignal(rg, GSN_CREATE_EVNT_REQ, signal, CreateEvntReq::SignalLength, JBB);
-}
-
-void
-Dbdict::createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI,
- Uint32 returnCode){
- OpCreateEventPtr evntRecPtr;
- c_opCreateEvent.getPtr(evntRecPtr, eventRecPtrI);
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-void Dbdict::execCREATE_EVNT_REF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
- CreateEvntRef * const ref = (CreateEvntRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = ref->getUserData();
-
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REF evntRecPtr.i = (%d)", evntRecPtr.i);
-#endif
-
- if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF){
- jam();
- evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(ref->senderRef));
- } else {
- jam();
- evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(ref->senderRef));
- }
- createEvent_sendReply(signal, evntRecPtr);
-
- return;
-}
-
-void Dbdict::execCREATE_EVNT_CONF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
- CreateEvntConf * const conf = (CreateEvntConf *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = conf->getUserData();
-
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_CONF evntRecPtr.i = (%d)", evntRecPtr.i);
-#endif
-
- evntRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(conf->senderRef));
-
- // we will only have a valid tablename if it the master DICT sending this
- // but that's ok
- LinearSectionPtr ptr[1];
- ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
- ptr[0].sz =
- (strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4; // to make sure we have a null
-
- createEvent_sendReply(signal, evntRecPtr, ptr, 1);
-
- return;
-}
-
-/************************************************
- *
- * Participant stuff
- *
- */
-
-void
-Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
- jam();
- evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Participant) got CREATE_EVNT_REQ::RT_DICT_AFTER_GET evntRecPtr.i = (%d)", evntRecPtr.i);
-#endif
-
- // the signal comes from the DICT block that got the first user request!
- // This code runs on all DICT nodes, including oneself
-
- // Seize a Create Event record, the Coordinator will now have two seized
- // but that's ok, it's like a recursion
-
- SubCreateReq * sumaReq = (SubCreateReq *)signal->getDataPtrSend();
-
- sumaReq->subscriberRef = reference(); // reference to DICT
- sumaReq->subscriberData = evntRecPtr.i;
- sumaReq->subscriptionId = evntRecPtr.p->m_request.getEventId();
- sumaReq->subscriptionKey = evntRecPtr.p->m_request.getEventKey();
- sumaReq->subscriptionType = SubCreateReq::TableEvent;
- sumaReq->tableId = evntRecPtr.p->m_request.getTableId();
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("sending GSN_SUB_CREATE_REQ");
-#endif
-
- sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ, signal,
- SubCreateReq::SignalLength+1 /*to get table Id*/, JBB);
-}
-
-void Dbdict::execSUB_CREATE_REF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
- SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = ref->subscriberData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Participant) got SUB_CREATE_REF evntRecPtr.i = (%d)", evntRecPtr.i);
-#endif
-
- if (ref->err == GrepError::SUBSCRIPTION_ID_NOT_UNIQUE) {
- jam();
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("SUBSCRIPTION_ID_NOT_UNIQUE");
-#endif
- createEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("Other error");
-#endif
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-void Dbdict::execSUB_CREATE_CONF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
-
- SubCreateConf * const sumaConf = (SubCreateConf *)signal->getDataPtr();
-
- const Uint32 subscriptionId = sumaConf->subscriptionId;
- const Uint32 subscriptionKey = sumaConf->subscriptionKey;
- const Uint32 evntRecId = sumaConf->subscriberData;
-
- OpCreateEvent *evntRec;
- ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL);
-
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT(Participant) got SUB_CREATE_CONF evntRecPtr.i = (%d)", evntRecId);
-#endif
-
- SubSyncReq *sumaSync = (SubSyncReq *)signal->getDataPtrSend();
-
- sumaSync->subscriptionId = subscriptionId;
- sumaSync->subscriptionKey = subscriptionKey;
- sumaSync->part = (Uint32) SubscriptionData::MetaData;
- sumaSync->subscriberData = evntRecId;
-
- sendSignal(SUMA_REF, GSN_SUB_SYNC_REQ, signal,
- SubSyncReq::SignalLength, JBB);
-}
-
-void Dbdict::execSUB_SYNC_REF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
- SubSyncRef * const ref = (SubSyncRef *)signal->getDataPtr();
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = ref->subscriberData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-void Dbdict::execSUB_SYNC_CONF(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
-
- SubSyncConf * const sumaSyncConf = (SubSyncConf *)signal->getDataPtr();
-
- // Uint32 subscriptionId = sumaSyncConf->subscriptionId;
- // Uint32 subscriptionKey = sumaSyncConf->subscriptionKey;
- OpCreateEventPtr evntRecPtr;
-
- evntRecPtr.i = sumaSyncConf->subscriberData;
- ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
-
- ndbrequire(sumaSyncConf->part == (Uint32)SubscriptionData::MetaData);
-
- createEvent_sendReply(signal, evntRecPtr);
-}
-
-/****************************************************
- *
- * common create reply method
- *
- *******************************************************/
-
-void Dbdict::createEvent_sendReply(Signal* signal,
- OpCreateEventPtr evntRecPtr,
- LinearSectionPtr *ptr, int noLSP)
-{
- jam();
- EVENT_TRACE;
-
- // check if we're ready to sent reply
- // if we are the master dict we might be waiting for conf/ref
-
- if (!evntRecPtr.p->m_reqTracker.done()) {
- jam();
- return; // there's more to come
- }
-
- if (evntRecPtr.p->m_reqTracker.hasRef()) {
- ptr = NULL; // we don't want to return anything if there's an error
- if (!evntRecPtr.p->hasError()) {
- evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
- jam();
- } else
- jam();
- }
-
- // reference to API if master DICT
- // else reference to master DICT
- Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
- Uint32 signalLength;
- Uint32 gsn;
-
- if (evntRecPtr.p->hasError()) {
- jam();
- EVENT_TRACE;
- CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
-
- ret->setEventId(evntRecPtr.p->m_request.getEventId());
- ret->setEventKey(evntRecPtr.p->m_request.getEventKey());
- ret->setUserData(evntRecPtr.p->m_request.getUserData());
- ret->senderRef = reference();
- ret->setTableId(evntRecPtr.p->m_request.getTableId());
- ret->setEventType(evntRecPtr.p->m_request.getEventType());
- ret->setRequestType(evntRecPtr.p->m_request.getRequestType());
-
- ret->setErrorCode(evntRecPtr.p->m_errorCode);
- ret->setErrorLine(evntRecPtr.p->m_errorLine);
- ret->setErrorNode(evntRecPtr.p->m_errorNode);
-
- signalLength = CreateEvntRef::SignalLength;
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT sending GSN_CREATE_EVNT_REF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
- ndbout_c("errorCode = %u", evntRecPtr.p->m_errorCode);
- ndbout_c("errorLine = %u", evntRecPtr.p->m_errorLine);
-#endif
- gsn = GSN_CREATE_EVNT_REF;
-
- } else {
- jam();
- EVENT_TRACE;
- CreateEvntConf * evntConf = (CreateEvntConf *)signal->getDataPtrSend();
-
- evntConf->setEventId(evntRecPtr.p->m_request.getEventId());
- evntConf->setEventKey(evntRecPtr.p->m_request.getEventKey());
- evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
- evntConf->senderRef = reference();
- evntConf->setTableId(evntRecPtr.p->m_request.getTableId());
- evntConf->setAttrListBitmask(evntRecPtr.p->m_request.getAttrListBitmask());
- evntConf->setEventType(evntRecPtr.p->m_request.getEventType());
- evntConf->setRequestType(evntRecPtr.p->m_request.getRequestType());
-
- signalLength = CreateEvntConf::SignalLength;
-#ifdef EVENT_PH2_DEBUG
- ndbout_c("DBDICT sending GSN_CREATE_EVNT_CONF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
-#endif
- gsn = GSN_CREATE_EVNT_CONF;
- }
-
- if (ptr) {
- jam();
- sendSignal(senderRef, gsn, signal, signalLength, JBB, ptr, noLSP);
- } else {
- jam();
- sendSignal(senderRef, gsn, signal, signalLength, JBB);
- }
-
- c_opCreateEvent.release(evntRecPtr);
-}
-
-/*************************************************************/
-
-/********************************************************************
- *
- * Start event
- *
- *******************************************************************/
-
-void Dbdict::execSUB_START_REQ(Signal* signal)
-{
- jamEntry();
-
- Uint32 origSenderRef = signal->senderBlockRef();
-
- OpSubEventPtr subbPtr;
- if (!c_opSubEvent.seize(subbPtr)) {
- SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
- { // fix
- Uint32 subcriberRef = ((SubStartReq*)signal->getDataPtr())->subscriberRef;
- ref->subscriberRef = subcriberRef;
- }
- jam();
- // ret->setErrorCode(SubStartRef::SeizeError);
- // ret->setErrorLine(__LINE__);
- // ret->setErrorNode(reference());
- ref->senderRef = reference();
- ref->setTemporary(SubStartRef::Busy);
-
- sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
- SubStartRef::SignalLength2, JBB);
- return;
- }
-
- {
- const SubStartReq* req = (SubStartReq*) signal->getDataPtr();
- subbPtr.p->m_senderRef = req->senderRef;
- subbPtr.p->m_senderData = req->senderData;
- subbPtr.p->m_errorCode = 0;
- }
-
- if (refToBlock(origSenderRef) != DBDICT) {
- /*
- * Coordinator
- */
- jam();
-
- subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- RequestTracker & p = subbPtr.p->m_reqTracker;
- p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i);
-
- SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
-
- req->senderRef = reference();
- req->senderData = subbPtr.i;
-
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("DBDICT(Coordinator) sending GSN_SUB_START_REQ to DBDICT participants subbPtr.i = (%d)", subbPtr.i);
-#endif
-
- sendSignal(rg, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength2, JBB);
- return;
- }
- /*
- * Participant
- */
- ndbrequire(refToBlock(origSenderRef) == DBDICT);
-
- {
- SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
-
- req->senderRef = reference();
- req->senderData = subbPtr.i;
-
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("DBDICT(Participant) sending GSN_SUB_START_REQ to SUMA subbPtr.i = (%d)", subbPtr.i);
-#endif
- sendSignal(SUMA_REF, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength2, JBB);
- }
-}
-
-void Dbdict::execSUB_START_REF(Signal* signal)
-{
- jamEntry();
-
- const SubStartRef* ref = (SubStartRef*) signal->getDataPtr();
- Uint32 senderRef = ref->senderRef;
-
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ref->senderData);
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
-
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("DBDICT(Participant) got GSN_SUB_START_REF = (%d)", subbPtr.i);
-#endif
-
- if (ref->isTemporary()){
- jam();
- SubStartReq* req = (SubStartReq*)signal->getDataPtrSend();
- { // fix
- Uint32 subscriberRef = ref->subscriberRef;
- req->subscriberRef = subscriberRef;
- }
- req->senderRef = reference();
- req->senderData = subbPtr.i;
- sendSignal(SUMA_REF, GSN_SUB_START_REQ,
- signal, SubStartReq::SignalLength2, JBB);
- } else {
- jam();
-
- SubStartRef* ref = (SubStartRef*) signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
- signal, SubStartRef::SignalLength2, JBB);
- c_opSubEvent.release(subbPtr);
- }
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_REF = (%d)", subbPtr.i);
-#endif
- if (ref->errorCode == SubStartRef::NF_FakeErrorREF){
- jam();
- subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
- } else {
- jam();
- subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
- }
- completeSubStartReq(signal,subbPtr.i,0);
-}
-
-void Dbdict::execSUB_START_CONF(Signal* signal)
-{
- jamEntry();
-
- const SubStartConf* conf = (SubStartConf*) signal->getDataPtr();
- Uint32 senderRef = conf->senderRef;
-
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, conf->senderData);
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- SubStartConf* conf = (SubStartConf*) signal->getDataPtrSend();
-
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("DBDICT(Participant) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
-#endif
-
- conf->senderRef = reference();
- conf->senderData = subbPtr.p->m_senderData;
-
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
- signal, SubStartConf::SignalLength2, JBB);
- c_opSubEvent.release(subbPtr);
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
-#endif
- subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
- completeSubStartReq(signal,subbPtr.i,0);
-}
-
-/*
- * Coordinator
- */
-void Dbdict::completeSubStartReq(Signal* signal,
- Uint32 ptrI,
- Uint32 returnCode){
- jam();
-
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ptrI);
-
- if (!subbPtr.p->m_reqTracker.done()){
- jam();
- return;
- }
-
- if (subbPtr.p->m_reqTracker.hasRef()) {
- jam();
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_START_REF");
-#endif
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
- signal, SubStartRef::SignalLength, JBB);
- if (subbPtr.p->m_reqTracker.hasConf()) {
- // stopStartedNodes(signal);
- }
- c_opSubEvent.release(subbPtr);
- return;
- }
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_START_CONF");
-#endif
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
- signal, SubStartConf::SignalLength, JBB);
- c_opSubEvent.release(subbPtr);
-}
-
-/********************************************************************
- *
- * Stop event
- *
- *******************************************************************/
-
-void Dbdict::execSUB_STOP_REQ(Signal* signal)
-{
- jamEntry();
-
- Uint32 origSenderRef = signal->senderBlockRef();
-
- OpSubEventPtr subbPtr;
- if (!c_opSubEvent.seize(subbPtr)) {
- SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
- jam();
- // ret->setErrorCode(SubStartRef::SeizeError);
- // ret->setErrorLine(__LINE__);
- // ret->setErrorNode(reference());
- ref->senderRef = reference();
- ref->setTemporary(SubStopRef::Busy);
-
- sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
- SubStopRef::SignalLength, JBB);
- return;
- }
-
- {
- const SubStopReq* req = (SubStopReq*) signal->getDataPtr();
- subbPtr.p->m_senderRef = req->senderRef;
- subbPtr.p->m_senderData = req->senderData;
- subbPtr.p->m_errorCode = 0;
- }
-
- if (refToBlock(origSenderRef) != DBDICT) {
- /*
- * Coordinator
- */
- jam();
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_STOP_REQ 1");
-#endif
- subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- RequestTracker & p = subbPtr.p->m_reqTracker;
- p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i);
-
- SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
-
- req->senderRef = reference();
- req->senderData = subbPtr.i;
-
- sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
- return;
- }
- /*
- * Participant
- */
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_STOP_REQ 2");
-#endif
- ndbrequire(refToBlock(origSenderRef) == DBDICT);
- {
- SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
-
- req->senderRef = reference();
- req->senderData = subbPtr.i;
-
- sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
- }
-}
-
-void Dbdict::execSUB_STOP_REF(Signal* signal)
-{
- jamEntry();
- const SubStopRef* ref = (SubStopRef*) signal->getDataPtr();
- Uint32 senderRef = ref->senderRef;
-
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ref->senderData);
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- if (ref->isTemporary()){
- jam();
- SubStopReq* req = (SubStopReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = subbPtr.i;
- sendSignal(SUMA_REF, GSN_SUB_STOP_REQ,
- signal, SubStopReq::SignalLength, JBB);
- } else {
- jam();
- SubStopRef* ref = (SubStopRef*) signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
- signal, SubStopRef::SignalLength, JBB);
- c_opSubEvent.release(subbPtr);
- }
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
- if (ref->errorCode == SubStopRef::NF_FakeErrorREF){
- jam();
- subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
- } else {
- jam();
- subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
- }
- completeSubStopReq(signal,subbPtr.i,0);
-}
-
-void Dbdict::execSUB_STOP_CONF(Signal* signal)
-{
- jamEntry();
-
- const SubStopConf* conf = (SubStopConf*) signal->getDataPtr();
- Uint32 senderRef = conf->senderRef;
-
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, conf->senderData);
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- SubStopConf* conf = (SubStopConf*) signal->getDataPtrSend();
-
- conf->senderRef = reference();
- conf->senderData = subbPtr.p->m_senderData;
-
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
- signal, SubStopConf::SignalLength, JBB);
- c_opSubEvent.release(subbPtr);
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
- subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
- completeSubStopReq(signal,subbPtr.i,0);
-}
-
-/*
- * Coordinator
- */
-void Dbdict::completeSubStopReq(Signal* signal,
- Uint32 ptrI,
- Uint32 returnCode){
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ptrI);
-
- if (!subbPtr.p->m_reqTracker.done()){
- jam();
- return;
- }
-
- if (subbPtr.p->m_reqTracker.hasRef()) {
- jam();
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_STOP_REF");
-#endif
- SubStopRef* ref = (SubStopRef*)signal->getDataPtrSend();
-
- ref->senderRef = reference();
- ref->senderData = subbPtr.p->m_senderData;
- /*
- ref->subscriptionId = subbPtr.p->m_senderData;
- ref->subscriptionKey = subbPtr.p->m_senderData;
- ref->part = subbPtr.p->m_part; // SubscriptionData::Part
- ref->subscriberData = subbPtr.p->m_subscriberData;
- ref->subscriberRef = subbPtr.p->m_subscriberRef;
- */
- ref->errorCode = subbPtr.p->m_errorCode;
-
-
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
- signal, SubStopRef::SignalLength, JBB);
- if (subbPtr.p->m_reqTracker.hasConf()) {
- // stopStartedNodes(signal);
- }
- c_opSubEvent.release(subbPtr);
- return;
- }
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_STOP_CONF");
-#endif
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
- signal, SubStopConf::SignalLength, JBB);
- c_opSubEvent.release(subbPtr);
-}
-
-/***************************************************************
- * MODULE: Drop event.
- *
- * Drop event.
- *
- * TODO
- */
-
-void
-Dbdict::execDROP_EVNT_REQ(Signal* signal)
-{
- jamEntry();
- EVENT_TRACE;
-
- DropEvntReq *req = (DropEvntReq*)signal->getDataPtr();
- const Uint32 senderRef = signal->senderBlockRef();
- OpDropEventPtr evntRecPtr;
-
- // Seize a Create Event record
- if (!c_opDropEvent.seize(evntRecPtr)) {
- // Failed to allocate event record
- jam();
- releaseSections(signal);
-
- DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
- ret->setErrorCode(DropEvntRef::SeizeError);
- ret->setErrorLine(__LINE__);
- ret->setErrorNode(reference());
- sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
- DropEvntRef::SignalLength, JBB);
- return;
- }
-
-#ifdef EVENT_DEBUG
- ndbout_c("DBDICT::execDROP_EVNT_REQ evntRecId = (%d)", evntRecPtr.i);
-#endif
-
- OpDropEvent* evntRec = evntRecPtr.p;
- evntRec->init(req);
-
- SegmentedSectionPtr ssPtr;
-
- signal->getSection(ssPtr, 0);
-
- SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
-#ifdef EVENT_DEBUG
- r0.printAll(ndbout);
-#endif
- // event name
- if ((!r0.first()) ||
- (r0.getValueType() != SimpleProperties::StringValue) ||
- (r0.getValueLen() <= 0)) {
- jam();
- releaseSections(signal);
-
- evntRecPtr.p->m_errorCode = DropEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorNode = reference();
-
- dropEvent_sendReply(signal, evntRecPtr);
- return;
- }
- r0.getString(evntRecPtr.p->m_eventRec.NAME);
- {
- int len = strlen(evntRecPtr.p->m_eventRec.NAME);
- memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
-#ifdef EVENT_DEBUG
- printf("DropEvntReq; EventName %s, len %u\n",
- evntRecPtr.p->m_eventRec.NAME, len);
- for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
- printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
- printf("\n");
-#endif
- }
-
- releaseSections(signal);
-
- Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_READ), 0 };
-
- prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
- UtilPrepareReq::Read);
-}
-
-void
-Dbdict::dropEventUTIL_PREPARE_READ(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- if (returnCode != 0) {
- EVENT_TRACE;
- dropEventUtilPrepareRef(signal, callbackData, returnCode);
- return;
- }
-
- UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
- OpDropEventPtr evntRecPtr;
- evntRecPtr.i = req->getSenderData();
- const Uint32 prepareId = req->getPrepareId();
-
- ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
-
- Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_READ), 0 };
-
- executeTransEventSysTable(&c, signal,
- evntRecPtr.i, evntRecPtr.p->m_eventRec,
- prepareId, UtilPrepareReq::Read);
-}
-
-void
-Dbdict::dropEventUTIL_EXECUTE_READ(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- if (returnCode != 0) {
- EVENT_TRACE;
- dropEventUtilExecuteRef(signal, callbackData, returnCode);
- return;
- }
-
- OpDropEventPtr evntRecPtr;
- UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
- jam();
- evntRecPtr.i = ref->getSenderData();
- ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
-
- parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
-
- NodeReceiverGroup rg(DBDICT, c_aliveNodes);
- RequestTracker & p = evntRecPtr.p->m_reqTracker;
- p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
- evntRecPtr.i);
-
- SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
-
- req->senderRef = reference();
- req->senderData = evntRecPtr.i;
- req->subscriptionId = evntRecPtr.p->m_eventRec.SUBID;
- req->subscriptionKey = evntRecPtr.p->m_eventRec.SUBKEY;
-
- sendSignal(rg, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
-}
-
-/*
- * Participant
- */
-
-void
-Dbdict::execSUB_REMOVE_REQ(Signal* signal)
-{
- jamEntry();
-
- Uint32 origSenderRef = signal->senderBlockRef();
-
- OpSubEventPtr subbPtr;
- if (!c_opSubEvent.seize(subbPtr)) {
- SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
- jam();
- ref->senderRef = reference();
- ref->setTemporary(SubRemoveRef::Busy);
-
- sendSignal(origSenderRef, GSN_SUB_REMOVE_REF, signal,
- SubRemoveRef::SignalLength, JBB);
- return;
- }
-
- {
- const SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtr();
- subbPtr.p->m_senderRef = req->senderRef;
- subbPtr.p->m_senderData = req->senderData;
- subbPtr.p->m_errorCode = 0;
- }
-
- SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = subbPtr.i;
-
- sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
-}
-
-/*
- * Coordintor/Participant
- */
-
-void
-Dbdict::execSUB_REMOVE_REF(Signal* signal)
-{
- jamEntry();
- const SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtr();
- Uint32 senderRef = ref->senderRef;
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, ref->senderData);
- if (ref->errorCode == (Uint32) GrepError::SUBSCRIPTION_ID_NOT_FOUND) {
- // conf this since this may occur if a nodefailiure has occured
- // earlier so that the systable was not cleared
- SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
- signal, SubRemoveConf::SignalLength, JBB);
- } else {
- SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_REF,
- signal, SubRemoveRef::SignalLength, JBB);
- }
- c_opSubEvent.release(subbPtr);
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
- OpDropEventPtr eventRecPtr;
- c_opDropEvent.getPtr(eventRecPtr, ref->senderData);
- if (ref->errorCode == SubRemoveRef::NF_FakeErrorREF){
- jam();
- eventRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
- } else {
- jam();
- eventRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
- }
- completeSubRemoveReq(signal,eventRecPtr.i,0);
-}
-
-void
-Dbdict::execSUB_REMOVE_CONF(Signal* signal)
-{
- jamEntry();
- const SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtr();
- Uint32 senderRef = conf->senderRef;
-
- if (refToBlock(senderRef) == SUMA) {
- /*
- * Participant
- */
- jam();
- OpSubEventPtr subbPtr;
- c_opSubEvent.getPtr(subbPtr, conf->senderData);
- SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = subbPtr.p->m_senderData;
- sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
- signal, SubRemoveConf::SignalLength, JBB);
- c_opSubEvent.release(subbPtr);
- return;
- }
- /*
- * Coordinator
- */
- ndbrequire(refToBlock(senderRef) == DBDICT);
- OpDropEventPtr eventRecPtr;
- c_opDropEvent.getPtr(eventRecPtr, conf->senderData);
- eventRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
- completeSubRemoveReq(signal,eventRecPtr.i,0);
-}
-
-void
-Dbdict::completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 xxx)
-{
- OpDropEventPtr evntRecPtr;
- c_opDropEvent.getPtr(evntRecPtr, ptrI);
-
- if (!evntRecPtr.p->m_reqTracker.done()){
- jam();
- return;
- }
-
- if (evntRecPtr.p->m_reqTracker.hasRef()) {
- jam();
- evntRecPtr.p->m_errorNode = reference();
- evntRecPtr.p->m_errorLine = __LINE__;
- evntRecPtr.p->m_errorCode = DropEvntRef::Undefined;
- dropEvent_sendReply(signal, evntRecPtr);
- return;
- }
-
- Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_DELETE), 0 };
-
- prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
- UtilPrepareReq::Delete);
-}
-
-void
-Dbdict::dropEventUTIL_PREPARE_DELETE(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- if (returnCode != 0) {
- EVENT_TRACE;
- dropEventUtilPrepareRef(signal, callbackData, returnCode);
- return;
- }
-
- UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
- OpDropEventPtr evntRecPtr;
- jam();
- evntRecPtr.i = req->getSenderData();
- const Uint32 prepareId = req->getPrepareId();
-
- ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
-#ifdef EVENT_DEBUG
- printf("DropEvntUTIL_PREPARE; evntRecPtr.i len %u\n",evntRecPtr.i);
-#endif
-
- Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_DELETE), 0 };
-
- executeTransEventSysTable(&c, signal,
- evntRecPtr.i, evntRecPtr.p->m_eventRec,
- prepareId, UtilPrepareReq::Delete);
-}
-
-void
-Dbdict::dropEventUTIL_EXECUTE_DELETE(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- if (returnCode != 0) {
- EVENT_TRACE;
- dropEventUtilExecuteRef(signal, callbackData, returnCode);
- return;
- }
-
- OpDropEventPtr evntRecPtr;
- UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
- jam();
- evntRecPtr.i = ref->getSenderData();
- ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
-
- dropEvent_sendReply(signal, evntRecPtr);
-}
-
-void
-Dbdict::dropEventUtilPrepareRef(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- UtilPrepareRef * const ref = (UtilPrepareRef *)signal->getDataPtr();
- OpDropEventPtr evntRecPtr;
- evntRecPtr.i = ref->getSenderData();
- ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
-
- bool temporary = false;
- interpretUtilPrepareErrorCode((UtilPrepareRef::ErrorCode)ref->getErrorCode(),
- temporary, evntRecPtr.p->m_errorLine);
- if (temporary) {
- evntRecPtr.p->m_errorCode = (DropEvntRef::ErrorCode)
- ((Uint32) DropEvntRef::Undefined | (Uint32) DropEvntRef::Temporary);
- }
-
- if (evntRecPtr.p->m_errorCode == 0) {
- evntRecPtr.p->m_errorCode = DropEvntRef::Undefined;
- evntRecPtr.p->m_errorLine = __LINE__;
- }
- evntRecPtr.p->m_errorNode = reference();
-
- dropEvent_sendReply(signal, evntRecPtr);
-}
-
-void
-Dbdict::dropEventUtilExecuteRef(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode)
-{
- jam();
- EVENT_TRACE;
- OpDropEventPtr evntRecPtr;
- UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
- jam();
- evntRecPtr.i = ref->getSenderData();
- ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
-
- evntRecPtr.p->m_errorNode = reference();
- evntRecPtr.p->m_errorLine = __LINE__;
-
- switch (ref->getErrorCode()) {
- case UtilExecuteRef::TCError:
- switch (ref->getTCErrorCode()) {
- case ZNOT_FOUND:
- jam();
- evntRecPtr.p->m_errorCode = DropEvntRef::EventNotFound;
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = DropEvntRef::UndefinedTCError;
- break;
- }
- break;
- default:
- jam();
- evntRecPtr.p->m_errorCode = DropEvntRef::Undefined;
- break;
- }
- dropEvent_sendReply(signal, evntRecPtr);
-}
-
-void Dbdict::dropEvent_sendReply(Signal* signal,
- OpDropEventPtr evntRecPtr)
-{
- jam();
- EVENT_TRACE;
- Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
-
- if (evntRecPtr.p->hasError()) {
- jam();
- DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
-
- ret->setUserData(evntRecPtr.p->m_request.getUserData());
- ret->setUserRef(evntRecPtr.p->m_request.getUserRef());
-
- ret->setErrorCode(evntRecPtr.p->m_errorCode);
- ret->setErrorLine(evntRecPtr.p->m_errorLine);
- ret->setErrorNode(evntRecPtr.p->m_errorNode);
-
- sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
- DropEvntRef::SignalLength, JBB);
- } else {
- jam();
- DropEvntConf * evntConf = (DropEvntConf *)signal->getDataPtrSend();
-
- evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
- evntConf->setUserRef(evntRecPtr.p->m_request.getUserRef());
-
- sendSignal(senderRef, GSN_DROP_EVNT_CONF, signal,
- DropEvntConf::SignalLength, JBB);
- }
-
- c_opDropEvent.release(evntRecPtr);
-}
/**
* MODULE: Alter index
@@ -9639,7 +7753,7 @@ Dbdict::alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr)
// broken index allowed if force
if (! (indexPtr.p->indexLocal & TableRecord::IL_CREATED_TC)) {
jam();
- ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
+ ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterIndex_sendReply(signal, opPtr, false);
return;
}
@@ -11696,7 +9810,7 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
// broken trigger allowed if force
if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_TC)) {
jam();
- ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
+ ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterTrigger_sendReply(signal, opPtr, false);
return;
}
@@ -11706,6 +9820,7 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
// broken trigger allowed if force
if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_LQH)) {
jam();
+ ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
alterTrigger_sendReply(signal, opPtr, false);
return;
}
@@ -11913,6 +10028,275 @@ Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
}
}
+// DICT lock master
+
+const Dbdict::DictLockType*
+Dbdict::getDictLockType(Uint32 lockType)
+{
+ static const DictLockType lt[] = {
+ { DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" }
+ };
+ for (int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
+ if (lt[i].lockType == lockType)
+ return &lt[i];
+ }
+ return NULL;
+}
+
+void
+Dbdict::sendDictLockInfoEvent(Uint32 pollCount)
+{
+ DictLockPtr loopPtr;
+ c_dictLockQueue.first(loopPtr);
+ unsigned count = 0;
+
+ char queue_buf[100];
+ char *p = &queue_buf[0];
+ const char *const q = &queue_buf[sizeof(queue_buf)];
+ *p = 0;
+
+ while (loopPtr.i != RNIL) {
+ jam();
+ my_snprintf(p, q-p, "%s%u%s",
+ ++count == 1 ? "" : " ",
+ (unsigned)refToNode(loopPtr.p->req.userRef),
+ loopPtr.p->locked ? "L" : "");
+ p += strlen(p);
+ c_dictLockQueue.next(loopPtr);
+ }
+
+ infoEvent("DICT: lock bs: %d ops: %d poll: %d cnt: %d queue: %s",
+ (int)c_blockState,
+ c_opRecordPool.getSize() - c_opRecordPool.getNoOfFree(),
+ c_dictLockPoll, (int)pollCount, queue_buf);
+}
+
+void
+Dbdict::sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text)
+{
+ infoEvent("DICT: %s %u for %s",
+ text,
+ (unsigned)refToNode(lockPtr.p->req.userRef), lockPtr.p->lt->text);
+}
+
+void
+Dbdict::execDICT_LOCK_REQ(Signal* signal)
+{
+ jamEntry();
+ const DictLockReq* req = (const DictLockReq*)&signal->theData[0];
+
+ // make sure bad request crashes slave, not master (us)
+
+ if (getOwnNodeId() != c_masterNodeId) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::NotMaster);
+ return;
+ }
+
+ const DictLockType* lt = getDictLockType(req->lockType);
+ if (lt == NULL) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::InvalidLockType);
+ return;
+ }
+
+ if (req->userRef != signal->getSendersBlockRef() ||
+ getNodeInfo(refToNode(req->userRef)).m_type != NodeInfo::DB) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::BadUserRef);
+ return;
+ }
+
+ if (c_aliveNodes.get(refToNode(req->userRef))) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::TooLate);
+ return;
+ }
+
+ DictLockPtr lockPtr;
+ if (! c_dictLockQueue.seize(lockPtr)) {
+ jam();
+ sendDictLockRef(signal, *req, DictLockRef::TooManyRequests);
+ return;
+ }
+
+ lockPtr.p->req = *req;
+ lockPtr.p->locked = false;
+ lockPtr.p->lt = lt;
+
+ checkDictLockQueue(signal, false);
+
+ if (! lockPtr.p->locked)
+ sendDictLockInfoEvent(lockPtr, "lock request by node");
+}
+
+void
+Dbdict::checkDictLockQueue(Signal* signal, bool poll)
+{
+ Uint32 pollCount = ! poll ? 0 : signal->theData[1];
+
+ DictLockPtr lockPtr;
+
+ do {
+ if (! c_dictLockQueue.first(lockPtr)) {
+ jam();
+ setDictLockPoll(signal, false, pollCount);
+ return;
+ }
+
+ if (lockPtr.p->locked) {
+ jam();
+ ndbrequire(c_blockState == lockPtr.p->lt->blockState);
+ break;
+ }
+
+ if (c_opRecordPool.getNoOfFree() != c_opRecordPool.getSize()) {
+ jam();
+ break;
+ }
+
+ ndbrequire(c_blockState == BS_IDLE);
+ lockPtr.p->locked = true;
+ c_blockState = lockPtr.p->lt->blockState;
+ sendDictLockConf(signal, lockPtr);
+
+ sendDictLockInfoEvent(lockPtr, "locked by node");
+ } while (0);
+
+ // poll while first request is open
+ // this routine is called again when it is removed for any reason
+
+ bool on = ! lockPtr.p->locked;
+ setDictLockPoll(signal, on, pollCount);
+}
+
+void
+Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
+{
+ jamEntry();
+ const DictUnlockOrd* ord = (const DictUnlockOrd*)&signal->theData[0];
+
+ DictLockPtr lockPtr;
+ c_dictLockQueue.getPtr(lockPtr, ord->lockPtr);
+ ndbrequire(lockPtr.p->lt->lockType == ord->lockType);
+
+ if (lockPtr.p->locked) {
+ jam();
+ ndbrequire(c_blockState == lockPtr.p->lt->blockState);
+ ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize());
+ ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
+
+ c_blockState = BS_IDLE;
+ sendDictLockInfoEvent(lockPtr, "unlocked by node");
+ } else {
+ sendDictLockInfoEvent(lockPtr, "lock request removed by node");
+ }
+
+ c_dictLockQueue.release(lockPtr);
+
+ checkDictLockQueue(signal, false);
+}
+
+void
+Dbdict::sendDictLockConf(Signal* signal, DictLockPtr lockPtr)
+{
+ DictLockConf* conf = (DictLockConf*)&signal->theData[0];
+ const DictLockReq& req = lockPtr.p->req;
+
+ conf->userPtr = req.userPtr;
+ conf->lockType = req.lockType;
+ conf->lockPtr = lockPtr.i;
+
+ sendSignal(req.userRef, GSN_DICT_LOCK_CONF, signal,
+ DictLockConf::SignalLength, JBB);
+}
+
+void
+Dbdict::sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode)
+{
+ DictLockRef* ref = (DictLockRef*)&signal->theData[0];
+
+ ref->userPtr = req.userPtr;
+ ref->lockType = req.lockType;
+ ref->errorCode = errorCode;
+
+ sendSignal(req.userRef, GSN_DICT_LOCK_REF, signal,
+ DictLockRef::SignalLength, JBB);
+}
+
+// control polling
+
+void
+Dbdict::setDictLockPoll(Signal* signal, bool on, Uint32 pollCount)
+{
+ if (on) {
+ jam();
+ signal->theData[0] = ZDICT_LOCK_POLL;
+ signal->theData[1] = pollCount + 1;
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
+ }
+
+ bool change = (c_dictLockPoll != on);
+
+ if (change) {
+ jam();
+ c_dictLockPoll = on;
+ }
+
+ // avoid too many messages if master is stuck busy (BS_NODE_FAILURE)
+ bool periodic =
+ pollCount < 8 ||
+ pollCount < 64 && pollCount % 8 == 0 ||
+ pollCount < 512 && pollCount % 64 == 0 ||
+ pollCount < 4096 && pollCount % 512 == 0 ||
+ pollCount % 4096 == 0; // about every 6 minutes
+
+ if (change || periodic)
+ sendDictLockInfoEvent(pollCount);
+}
+
+// NF handling
+
+void
+Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
+{
+ DictLockPtr loopPtr;
+ c_dictLockQueue.first(loopPtr);
+
+ if (getOwnNodeId() != c_masterNodeId) {
+ ndbrequire(loopPtr.i == RNIL);
+ return;
+ }
+
+ while (loopPtr.i != RNIL) {
+ jam();
+ DictLockPtr lockPtr = loopPtr;
+ c_dictLockQueue.next(loopPtr);
+
+ Uint32 nodeId = refToNode(lockPtr.p->req.userRef);
+
+ if (NodeBitmask::get(theFailedNodes, nodeId)) {
+ if (lockPtr.p->locked) {
+ jam();
+ ndbrequire(c_blockState == lockPtr.p->lt->blockState);
+ ndbrequire(c_opRecordPool.getNoOfFree() == c_opRecordPool.getSize());
+ ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
+
+ c_blockState = BS_IDLE;
+
+ sendDictLockInfoEvent(lockPtr, "remove lock by failed node");
+ } else {
+ sendDictLockInfoEvent(lockPtr, "remove lock request by failed node");
+ }
+
+ c_dictLockQueue.release(lockPtr);
+ }
+ }
+
+ checkDictLockQueue(signal, false);
+}
+
+
/* **************************************************************** */
/* ---------------------------------------------------------------- */
/* MODULE: STORE/RESTORE SCHEMA FILE---------------------- */
@@ -11924,36 +10308,75 @@ Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
/* **************************************************************** */
void
-Dbdict::initSchemaFile(SchemaFile * sf, Uint32 fileSz){
- memcpy(sf->Magic, "NDBSCHMA", sizeof(sf->Magic));
- sf->ByteOrder = 0x12345678;
- sf->NdbVersion = NDB_VERSION;
- sf->FileSize = fileSz;
- sf->CheckSum = 0;
-
- Uint32 headSz = (sizeof(SchemaFile)-sizeof(SchemaFile::TableEntry));
- Uint32 noEntries = (fileSz - headSz) / sizeof(SchemaFile::TableEntry);
- Uint32 slack = (fileSz - headSz) - noEntries * sizeof(SchemaFile::TableEntry);
-
- ndbrequire(noEntries > MAX_TABLES);
+Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage,
+ bool initEntries)
+{
+ ndbrequire(lastPage <= xsf->noOfPages);
+ for (Uint32 n = firstPage; n < lastPage; n++) {
+ SchemaFile * sf = &xsf->schemaPage[n];
+ if (initEntries)
+ memset(sf, 0, NDB_SF_PAGE_SIZE);
+
+ Uint32 ndb_version = NDB_VERSION;
+ if (ndb_version < NDB_SF_VERSION_5_0_6)
+ ndb_version = NDB_SF_VERSION_5_0_6;
- sf->NoOfTableEntries = noEntries;
- memset(sf->TableEntries, 0, noEntries*sizeof(SchemaFile::TableEntry));
- memset(&(sf->TableEntries[noEntries]), 0, slack);
- computeChecksum(sf);
+ memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic));
+ sf->ByteOrder = 0x12345678;
+ sf->NdbVersion = ndb_version;
+ sf->FileSize = xsf->noOfPages * NDB_SF_PAGE_SIZE;
+ sf->PageNumber = n;
+ sf->CheckSum = 0;
+ sf->NoOfTableEntries = NDB_SF_PAGE_ENTRIES;
+
+ computeChecksum(xsf, n);
+ }
}
void
-Dbdict::computeChecksum(SchemaFile * sf){
+Dbdict::resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages)
+{
+ ndbrequire(noOfPages <= NDB_SF_MAX_PAGES);
+ if (xsf->noOfPages < noOfPages) {
+ jam();
+ Uint32 firstPage = xsf->noOfPages;
+ xsf->noOfPages = noOfPages;
+ initSchemaFile(xsf, 0, firstPage, false);
+ initSchemaFile(xsf, firstPage, xsf->noOfPages, true);
+ }
+ if (xsf->noOfPages > noOfPages) {
+ jam();
+ Uint32 tableId = noOfPages * NDB_SF_PAGE_ENTRIES;
+ while (tableId < xsf->noOfPages * NDB_SF_PAGE_ENTRIES) {
+ SchemaFile::TableEntry * te = getTableEntry(xsf, tableId);
+ if (te->m_tableState != SchemaFile::INIT &&
+ te->m_tableState != SchemaFile::DROP_TABLE_COMMITTED) {
+ ndbrequire(false);
+ }
+ tableId++;
+ }
+ xsf->noOfPages = noOfPages;
+ initSchemaFile(xsf, 0, xsf->noOfPages, false);
+ }
+}
+
+void
+Dbdict::computeChecksum(XSchemaFile * xsf, Uint32 pageNo){
+ SchemaFile * sf = &xsf->schemaPage[pageNo];
sf->CheckSum = 0;
- sf->CheckSum = computeChecksum((const Uint32*)sf, sf->FileSize/4);
+ sf->CheckSum = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
}
bool
-Dbdict::validateChecksum(const SchemaFile * sf){
+Dbdict::validateChecksum(const XSchemaFile * xsf){
- Uint32 c = computeChecksum((const Uint32*)sf, sf->FileSize/4);
- return c == 0;
+ for (Uint32 n = 0; n < xsf->noOfPages; n++) {
+ SchemaFile * sf = &xsf->schemaPage[n];
+ Uint32 c = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
+ if ( c != 0)
+ return false;
+ }
+ return true;
}
Uint32
@@ -11965,11 +10388,14 @@ Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
}
SchemaFile::TableEntry *
-Dbdict::getTableEntry(void * p, Uint32 tableId, bool allowTooBig){
- SchemaFile * sf = (SchemaFile*)p;
-
- ndbrequire(allowTooBig || tableId < sf->NoOfTableEntries);
- return &sf->TableEntries[tableId];
+Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
+{
+ Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
+ Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
+ ndbrequire(n < xsf->noOfPages);
+
+ SchemaFile * sf = &xsf->schemaPage[n];
+ return &sf->TableEntries[i];
}
// global metadata support
@@ -12074,3 +10500,5 @@ Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table
new (&attr) MetaData::Attribute(*attrPtr.p);
return 0;
}
+
+CArray<KeyDescriptor> g_key_descriptor_pool;
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index bcee4a52b6a..ed8b7e3b822 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -26,6 +26,7 @@
#include <pc.hpp>
#include <ArrayList.hpp>
#include <DLHashTable.hpp>
+#include <DLFifoList.hpp>
#include <CArray.hpp>
#include <KeyTable2.hpp>
#include <SimulatedBlock.hpp>
@@ -45,11 +46,10 @@
#include <signaldata/DropIndx.hpp>
#include <signaldata/AlterIndx.hpp>
#include <signaldata/BuildIndx.hpp>
-#include <signaldata/UtilPrepare.hpp>
-#include <signaldata/CreateEvnt.hpp>
#include <signaldata/CreateTrig.hpp>
#include <signaldata/DropTrig.hpp>
#include <signaldata/AlterTrig.hpp>
+#include <signaldata/DictLock.hpp>
#include "SchemaFile.hpp"
#include <blocks/mutexes.hpp>
#include <SafeCounter.hpp>
@@ -63,6 +63,7 @@
/*--------------------------------------------------------------*/
#define ZPACK_TABLE_INTO_PAGES 0
#define ZSEND_GET_TAB_RESPONSE 3
+#define ZDICT_LOCK_POLL 4
/*--------------------------------------------------------------*/
@@ -78,7 +79,8 @@
/*--------------------------------------------------------------*/
// Page constants
/*--------------------------------------------------------------*/
-#define ZALLOCATE 1 //Variable number of page for NDBFS
+#define ZBAT_SCHEMA_FILE 0 //Variable number of page for NDBFS
+#define ZBAT_TABLE_FILE 1 //Variable number of page for NDBFS
#define ZPAGE_HEADER_SIZE 32
#define ZPOS_PAGE_SIZE 16
#define ZPOS_CHECKSUM 17
@@ -92,7 +94,7 @@
#define ZSIZE_OF_PAGES_IN_WORDS 8192
#define ZLOG_SIZE_OF_PAGES_IN_WORDS 13
#define ZMAX_PAGES_OF_TABLE_DEFINITION 8
-#define ZNUMBER_OF_PAGES (2 * ZMAX_PAGES_OF_TABLE_DEFINITION + 2)
+#define ZNUMBER_OF_PAGES (ZMAX_PAGES_OF_TABLE_DEFINITION + 1)
#define ZNO_OF_FRAGRECORD 5
/*--------------------------------------------------------------*/
@@ -130,6 +132,10 @@ public:
* on disk. Index trigger ids are volatile.
*/
struct TableRecord : public MetaData::Table {
+ Uint32 maxRowsLow;
+ Uint32 maxRowsHigh;
+ Uint32 minRowsLow;
+ Uint32 minRowsHigh;
/****************************************************
* Support variables for table handling
****************************************************/
@@ -212,7 +218,9 @@ public:
IL_CREATED_TC = 1 << 0 // created in TC
};
Uint32 indexLocal;
-
+
+ Uint32 noOfNullBits;
+
inline bool equal(TableRecord & rec) const {
return strcmp(tableName, rec.tableName) == 0;
}
@@ -426,6 +434,12 @@ public:
typedef Ptr<PageRecord> PageRecordPtr;
CArray<PageRecord> c_pageRecordArray;
+ struct SchemaPageRecord {
+ Uint32 word[NDB_SF_PAGE_SIZE_IN_WORDS];
+ };
+
+ CArray<SchemaPageRecord> c_schemaPageRecordArray;
+
/**
* A page for create index table signal.
*/
@@ -501,45 +515,6 @@ private:
void execBACKUP_FRAGMENT_REQ(Signal*);
- // Util signals used by Event code
- void execUTIL_PREPARE_CONF(Signal* signal);
- void execUTIL_PREPARE_REF (Signal* signal);
- void execUTIL_EXECUTE_CONF(Signal* signal);
- void execUTIL_EXECUTE_REF (Signal* signal);
- void execUTIL_RELEASE_CONF(Signal* signal);
- void execUTIL_RELEASE_REF (Signal* signal);
-
-
- // Event signals from API
- void execCREATE_EVNT_REQ (Signal* signal);
- void execCREATE_EVNT_CONF(Signal* signal);
- void execCREATE_EVNT_REF (Signal* signal);
-
- void execDROP_EVNT_REQ (Signal* signal);
-
- void execSUB_START_REQ (Signal* signal);
- void execSUB_START_CONF (Signal* signal);
- void execSUB_START_REF (Signal* signal);
-
- void execSUB_STOP_REQ (Signal* signal);
- void execSUB_STOP_CONF (Signal* signal);
- void execSUB_STOP_REF (Signal* signal);
-
- // Event signals from SUMA
-
- void execCREATE_SUBID_CONF(Signal* signal);
- void execCREATE_SUBID_REF (Signal* signal);
-
- void execSUB_CREATE_CONF(Signal* signal);
- void execSUB_CREATE_REF (Signal* signal);
-
- void execSUB_SYNC_CONF(Signal* signal);
- void execSUB_SYNC_REF (Signal* signal);
-
- void execSUB_REMOVE_REQ(Signal* signal);
- void execSUB_REMOVE_CONF(Signal* signal);
- void execSUB_REMOVE_REF(Signal* signal);
-
// Trigger signals
void execCREATE_TRIG_REQ(Signal* signal);
void execCREATE_TRIG_CONF(Signal* signal);
@@ -578,6 +553,9 @@ private:
void execALTER_TAB_CONF(Signal* signal);
bool check_ndb_versions() const;
+ void execDICT_LOCK_REQ(Signal* signal);
+ void execDICT_UNLOCK_ORD(Signal* signal);
+
/*
* 2.4 COMMON STORED VARIABLES
*/
@@ -653,16 +631,20 @@ private:
struct ReadSchemaRecord {
/** Page Id of schema page */
Uint32 pageId;
+ /** First page to read */
+ Uint32 firstPage;
+ /** Number of pages to read */
+ Uint32 noOfPages;
/** State, indicates from where it was called */
enum SchemaReadState {
IDLE = 0,
- INITIAL_READ = 1
+ INITIAL_READ_HEAD = 1,
+ INITIAL_READ = 2
};
SchemaReadState schemaReadState;
};
ReadSchemaRecord c_readSchemaRecord;
-private:
/**
* This record stores all the state needed
* when a schema file is being written to disk
@@ -670,6 +652,12 @@ private:
struct WriteSchemaRecord {
/** Page Id of schema page */
Uint32 pageId;
+ /** Rewrite entire file */
+ Uint32 newFile;
+ /** First page to write */
+ Uint32 firstPage;
+ /** Number of pages to write */
+ Uint32 noOfPages;
/** Schema Files Handled, local state variable */
Uint32 noOfSchemaFilesHandled;
@@ -750,21 +738,33 @@ private:
* Word 4: Currently zero
****************************************************************************/
struct SchemaRecord {
- /** Schema page */
+ /** Schema file first page (0) */
Uint32 schemaPage;
- /** Old Schema page (used at node restart) */
+ /** Old Schema file first page (used at node restart) */
Uint32 oldSchemaPage;
Callback m_callback;
};
SchemaRecord c_schemaRecord;
- void initSchemaFile(SchemaFile *, Uint32 sz);
- void computeChecksum(SchemaFile *);
- bool validateChecksum(const SchemaFile *);
- SchemaFile::TableEntry * getTableEntry(void * buf, Uint32 tableId,
- bool allowTooBig = false);
+ /*
+ * Schema file, list of schema pages. Use an array until a pool
+ * exists and NDBFS interface can use it.
+ */
+ struct XSchemaFile {
+ SchemaFile* schemaPage;
+ Uint32 noOfPages;
+ };
+ // 0-normal 1-old
+ XSchemaFile c_schemaFile[2];
+
+ void initSchemaFile(XSchemaFile *, Uint32 firstPage, Uint32 lastPage,
+ bool initEntries);
+ void resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages);
+ void computeChecksum(XSchemaFile *, Uint32 pageNo);
+ bool validateChecksum(const XSchemaFile *);
+ SchemaFile::TableEntry * getTableEntry(XSchemaFile *, Uint32 tableId);
Uint32 computeChecksum(const Uint32 * src, Uint32 len);
@@ -786,12 +786,43 @@ private:
// State variables
/* ----------------------------------------------------------------------- */
+#ifndef ndb_dbdict_log_block_state
enum BlockState {
BS_IDLE = 0,
BS_CREATE_TAB = 1,
BS_BUSY = 2,
- BS_NODE_FAILURE = 3
+ BS_NODE_FAILURE = 3,
+ BS_NODE_RESTART = 4
+ };
+#else // quick hack to log changes
+ enum {
+ BS_IDLE = 0,
+ BS_CREATE_TAB = 1,
+ BS_BUSY = 2,
+ BS_NODE_FAILURE = 3,
+ BS_NODE_RESTART = 4
};
+ struct BlockState;
+ friend struct BlockState;
+ struct BlockState {
+ BlockState() :
+ m_value(BS_IDLE) {
+ }
+ BlockState(int value) :
+ m_value(value) {
+ }
+ operator int() const {
+ return m_value;
+ }
+ BlockState& operator=(const BlockState& bs) {
+ Dbdict* dict = (Dbdict*)globalData.getBlock(DBDICT);
+ dict->infoEvent("DICT: bs %d->%d", m_value, bs.m_value);
+ m_value = bs.m_value;
+ return *this;
+ }
+ int m_value;
+ };
+#endif
BlockState c_blockState;
struct PackTable {
@@ -1314,119 +1345,6 @@ private:
typedef Ptr<OpBuildIndex> OpBuildIndexPtr;
/**
- * Operation record for Util Signals.
- */
- struct OpSignalUtil : OpRecordCommon{
- Callback m_callback;
- Uint32 m_userData;
- };
- typedef Ptr<OpSignalUtil> OpSignalUtilPtr;
-
- /**
- * Operation record for subscribe-start-stop
- */
- struct OpSubEvent : OpRecordCommon {
- Uint32 m_senderRef;
- Uint32 m_senderData;
- Uint32 m_errorCode;
- RequestTracker m_reqTracker;
- };
- typedef Ptr<OpSubEvent> OpSubEventPtr;
-
- static const Uint32 sysTab_NDBEVENTS_0_szs[];
-
- /**
- * Operation record for create event.
- */
- struct OpCreateEvent : OpRecordCommon {
- // original request (event id will be added)
- CreateEvntReq m_request;
- //AttributeMask m_attrListBitmask;
- // AttributeList m_attrList;
- sysTab_NDBEVENTS_0 m_eventRec;
- // char m_eventName[MAX_TAB_NAME_SIZE];
- // char m_tableName[MAX_TAB_NAME_SIZE];
-
- // coordinator DICT
- RequestTracker m_reqTracker;
- // state info
- CreateEvntReq::RequestType m_requestType;
- Uint32 m_requestFlag;
- // error info
- CreateEvntRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // ctor
- OpCreateEvent() {
- memset(&m_request, 0, sizeof(m_request));
- m_requestType = CreateEvntReq::RT_UNDEFINED;
- m_requestFlag = 0;
- m_errorCode = CreateEvntRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void init(const CreateEvntReq* req, Dbdict* dp) {
- m_request = *req;
- m_errorCode = CreateEvntRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- m_requestType = req->getRequestType();
- m_requestFlag = req->getRequestFlag();
- }
- bool hasError() {
- return m_errorCode != CreateEvntRef::NoError;
- }
- void setError(const CreateEvntRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
-
- };
- typedef Ptr<OpCreateEvent> OpCreateEventPtr;
-
- /**
- * Operation record for drop event.
- */
- struct OpDropEvent : OpRecordCommon {
- // original request
- DropEvntReq m_request;
- // char m_eventName[MAX_TAB_NAME_SIZE];
- sysTab_NDBEVENTS_0 m_eventRec;
- RequestTracker m_reqTracker;
- // error info
- DropEvntRef::ErrorCode m_errorCode;
- Uint32 m_errorLine;
- Uint32 m_errorNode;
- // ctor
- OpDropEvent() {
- memset(&m_request, 0, sizeof(m_request));
- m_errorCode = DropEvntRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- void init(const DropEvntReq* req) {
- m_request = *req;
- m_errorCode = DropEvntRef::NoError;
- m_errorLine = 0;
- m_errorNode = 0;
- }
- bool hasError() {
- return m_errorCode != DropEvntRef::NoError;
- }
- void setError(const DropEvntRef* ref) {
- if (ref != 0 && ! hasError()) {
- m_errorCode = ref->getErrorCode();
- m_errorLine = ref->getErrorLine();
- m_errorNode = ref->getErrorNode();
- }
- }
- };
- typedef Ptr<OpDropEvent> OpDropEventPtr;
-
- /**
* Operation record for create trigger.
*/
struct OpCreateTrigger : OpRecordCommon {
@@ -1646,10 +1564,6 @@ public:
STATIC_CONST( opDropIndexSize = sizeof(OpDropIndex) );
STATIC_CONST( opAlterIndexSize = sizeof(OpAlterIndex) );
STATIC_CONST( opBuildIndexSize = sizeof(OpBuildIndex) );
- STATIC_CONST( opCreateEventSize = sizeof(OpCreateEvent) );
- STATIC_CONST( opSubEventSize = sizeof(OpSubEvent) );
- STATIC_CONST( opDropEventSize = sizeof(OpDropEvent) );
- STATIC_CONST( opSignalUtilSize = sizeof(OpSignalUtil) );
STATIC_CONST( opCreateTriggerSize = sizeof(OpCreateTrigger) );
STATIC_CONST( opDropTriggerSize = sizeof(OpDropTrigger) );
STATIC_CONST( opAlterTriggerSize = sizeof(OpAlterTrigger) );
@@ -1660,10 +1574,6 @@ private:
Uint32 u_opDropTable [PTR_ALIGN(opDropTableSize)];
Uint32 u_opCreateIndex [PTR_ALIGN(opCreateIndexSize)];
Uint32 u_opDropIndex [PTR_ALIGN(opDropIndexSize)];
- Uint32 u_opCreateEvent [PTR_ALIGN(opCreateEventSize)];
- Uint32 u_opSubEvent [PTR_ALIGN(opSubEventSize)];
- Uint32 u_opDropEvent [PTR_ALIGN(opDropEventSize)];
- Uint32 u_opSignalUtil [PTR_ALIGN(opSignalUtilSize)];
Uint32 u_opAlterIndex [PTR_ALIGN(opAlterIndexSize)];
Uint32 u_opBuildIndex [PTR_ALIGN(opBuildIndexSize)];
Uint32 u_opCreateTrigger[PTR_ALIGN(opCreateTriggerSize)];
@@ -1680,10 +1590,6 @@ private:
KeyTable2<OpDropIndex, OpRecordUnion> c_opDropIndex;
KeyTable2<OpAlterIndex, OpRecordUnion> c_opAlterIndex;
KeyTable2<OpBuildIndex, OpRecordUnion> c_opBuildIndex;
- KeyTable2<OpCreateEvent, OpRecordUnion> c_opCreateEvent;
- KeyTable2<OpSubEvent, OpRecordUnion> c_opSubEvent;
- KeyTable2<OpDropEvent, OpRecordUnion> c_opDropEvent;
- KeyTable2<OpSignalUtil, OpRecordUnion> c_opSignalUtil;
KeyTable2<OpCreateTrigger, OpRecordUnion> c_opCreateTrigger;
KeyTable2<OpDropTrigger, OpRecordUnion> c_opDropTrigger;
KeyTable2<OpAlterTrigger, OpRecordUnion> c_opAlterTrigger;
@@ -1691,6 +1597,70 @@ private:
// Unique key for operation XXX move to some system table
Uint32 c_opRecordSequence;
+ /*
+ * Master DICT can be locked in 2 mutually exclusive ways:
+ *
+ * 1) for schema ops, via operation records
+ * 2) against schema ops, via a lock queue
+ *
+ * Current use of 2) is by a starting node, to prevent schema ops
+ * until started. The ops are refused (BlockState != BS_IDLE),
+ * not queued.
+ *
+ * Master failure is not handled, in node start case the starting
+ * node will crash too anyway. Use lock table in future..
+ *
+ * The lock queue is "serial" but other behaviour is possible
+ * by checking lock types e.g. to allow parallel node starts.
+ *
+ * Checking release of last op record is not convenient with
+ * current structure (5.0). Instead we poll via continueB.
+ *
+ * XXX only table ops check BlockState
+ */
+ struct DictLockType;
+ friend struct DictLockType;
+
+ struct DictLockType {
+ DictLockReq::LockType lockType;
+ BlockState blockState;
+ const char* text;
+ };
+
+ struct DictLockRecord;
+ friend struct DictLockRecord;
+
+ struct DictLockRecord {
+ DictLockReq req;
+ const DictLockType* lt;
+ bool locked;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+
+ typedef Ptr<DictLockRecord> DictLockPtr;
+ ArrayPool<DictLockRecord> c_dictLockPool;
+ DLFifoList<DictLockRecord> c_dictLockQueue;
+ bool c_dictLockPoll;
+
+ static const DictLockType* getDictLockType(Uint32 lockType);
+ void sendDictLockInfoEvent(Uint32 pollCount);
+ void sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text);
+
+ void checkDictLockQueue(Signal* signal, bool poll);
+ void sendDictLockConf(Signal* signal, DictLockPtr lockPtr);
+ void sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode);
+
+ // control polling i.e. continueB loop
+ void setDictLockPoll(Signal* signal, bool on, Uint32 pollCount);
+
+ // NF handling
+ void removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes);
+
+
// Statement blocks
/* ------------------------------------------------------------ */
@@ -1713,7 +1683,8 @@ private:
bool getNewAttributeRecord(TableRecordPtr tablePtr,
AttributeRecordPtr & attrPtr);
void packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId);
- void packTableIntoPagesImpl(SimpleProperties::Writer &, TableRecordPtr);
+ void packTableIntoPagesImpl(SimpleProperties::Writer &, TableRecordPtr,
+ Signal* signal= 0);
void sendGET_TABINFOREQ(Signal* signal,
Uint32 tableId);
@@ -1761,7 +1732,8 @@ private:
void openSchemaFile(Signal* signal,
Uint32 fileNo,
Uint32 fsPtr,
- bool writeFlag);
+ bool writeFlag,
+ bool newFile);
void writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
void writeSchemaConf(Signal* signal,
FsConnectRecordPtr fsPtr);
@@ -1803,6 +1775,7 @@ private:
void readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr);
void closeReadSchemaConf(Signal* signal,
FsConnectRecordPtr fsPtr);
+ bool convertSchemaFileTo_5_0_6(XSchemaFile*);
/* ------------------------------------------------------------ */
// Get table definitions
@@ -1880,101 +1853,6 @@ private:
void buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr);
void buildIndex_sendReply(Signal* signal, OpBuildIndexPtr opPtr, bool);
- // Events
- void
- createEventUTIL_PREPARE(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- createEventUTIL_EXECUTE(Signal *signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- dropEventUTIL_PREPARE_READ(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- dropEventUTIL_EXECUTE_READ(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- dropEventUTIL_PREPARE_DELETE(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- dropEventUTIL_EXECUTE_DELETE(Signal *signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- dropEventUtilPrepareRef(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- void
- dropEventUtilExecuteRef(Signal* signal,
- Uint32 callbackData,
- Uint32 returnCode);
- int
- sendSignalUtilReq(Callback *c,
- BlockReference ref,
- GlobalSignalNumber gsn,
- Signal* signal,
- Uint32 length,
- JobBufferLevel jbuf,
- LinearSectionPtr ptr[3],
- Uint32 noOfSections);
- int
- recvSignalUtilReq(Signal* signal, Uint32 returnCode);
-
- void completeSubStartReq(Signal* signal, Uint32 ptrI, Uint32 returnCode);
- void completeSubStopReq(Signal* signal, Uint32 ptrI, Uint32 returnCode);
- void completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 returnCode);
-
- void dropEvent_sendReply(Signal* signal,
- OpDropEventPtr evntRecPtr);
-
- void createEvent_RT_USER_CREATE(Signal* signal, OpCreateEventPtr evntRecPtr);
- void createEventComplete_RT_USER_CREATE(Signal* signal,
- OpCreateEventPtr evntRecPtr);
- void createEvent_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr);
- void createEventComplete_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr);
-
- void createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr);
-
- void createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI,
- Uint32 returnCode);
- void createEvent_sendReply(Signal* signal, OpCreateEventPtr evntRecPtr,
- LinearSectionPtr *ptr = NULL, int noLSP = 0);
-
- void prepareTransactionEventSysTable (Callback *c,
- Signal* signal,
- Uint32 senderData,
- UtilPrepareReq::OperationTypeValue prepReq);
- void prepareUtilTransaction(Callback *c,
- Signal* signal,
- Uint32 senderData,
- Uint32 tableId,
- const char *tableName,
- UtilPrepareReq::OperationTypeValue prepReq,
- Uint32 noAttr,
- Uint32 attrIds[],
- const char *attrNames[]);
-
- void executeTransEventSysTable(Callback *c,
- Signal *signal,
- const Uint32 ptrI,
- sysTab_NDBEVENTS_0& m_eventRec,
- const Uint32 prepareId,
- UtilPrepareReq::OperationTypeValue prepReq);
- void executeTransaction(Callback *c,
- Signal* signal,
- Uint32 senderData,
- Uint32 prepareId,
- Uint32 noAttr,
- LinearSectionPtr headerPtr,
- LinearSectionPtr dataPtr);
-
- void parseReadEventSys(Signal *signal, sysTab_NDBEVENTS_0& m_eventRec);
-
// create trigger
void createTrigger_recvReply(Signal* signal, const CreateTrigConf* conf,
const CreateTrigRef* ref);
diff --git a/ndb/src/kernel/blocks/dbdict/DictLock.txt b/ndb/src/kernel/blocks/dbdict/DictLock.txt
new file mode 100644
index 00000000000..72e23ed15a5
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbdict/DictLock.txt
@@ -0,0 +1,98 @@
+Lock master DICT against schema operations
+
+Implementation
+--------------
+
+[ see comments in Dbdict.hpp ]
+
+Use case: Node startup INR / NR
+-------------------------------
+
+Master DICT (like any block) keeps list of alive nodes (c_aliveNodes).
+These are participants in schema ops.
+
+(1) c_aliveNodes is initialized when DICT starts
+ in sp3 in READ_NODESCONF from CNTR
+
+(2) when slave node fails (in any sp of the slave node)
+ it is removed from c_aliveNodes in NODE_FAILREP
+
+(3) when slave starts, it is added to c_aliveNodes
+ in sp4 of the starting node in INCL_NODEREQ
+
+Slave DIH locks master DICT in sp2 and releases the lock when started.
+Based on the constraints:
+
+- the lock is taken when master DICT is known
+ DIH reads this in sp2 in READ_NODESCONF
+
+- the lock is taken before (3)
+
+- the lock is taken before copying starts and held until it is done
+ in sp4 DIH meta, DICT meta, tuple data
+
+- on INR in sp2 in START_PERMREQ the LCP info of the slave is erased
+ in all DIH in invalidateNodeLCP() - not safe under schema ops
+
+Signals:
+
+All but DICT_LOCK are standard v5.0 signals.
+s=starting node, m=master, a=all participants, l=local block.
+
+* sp2 - DICT_LOCK and START_PERM
+
+DIH/s
+ DICT_LOCK_REQ
+ DICT/m
+ DICT_LOCK_CONF
+DIH/s
+ START_PERMREQ
+ DIH/m
+ START_INFOREQ
+ DIH/a
+ invalidateNodeLCP() if INR
+ DIH/a
+ START_INFOCONF
+ DIH/m
+ START_PERMCONF
+DIH/s
+
+* sp4 - START_ME (copy metadata, no changes)
+
+DIH/s
+ START_MEREQ
+ DIH/m
+ COPY_TABREQ
+ DIH/s
+ COPY_TABCONF
+ DIH/m
+ DICTSTARTREQ
+ DICT/s
+ GET_SCHEMA_INFOREQ
+ DICT/m
+ SCHEMA_INFO
+ DICT/s
+ DICTSTARTCONF
+ DIH/m
+ INCL_NODEREQ
+ DIH/a
+ INCL_NODEREQ
+ ANY/l
+ INCL_NODECONF
+ DIH/a
+ INCL_NODECONF
+ DIH/m
+ START_MECONF
+DIH/s
+
+* (copy data, omitted)
+
+* SL_STARTED - release DICT lock
+
+CNTR/s
+ NODE_START_REP
+ DIH/s
+ DICT_UNLOCK_ORD
+ DICT/m
+
+# vim: set et sw=4:
diff --git a/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp b/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
index 7c3223d3d14..0226991a073 100644
--- a/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
+++ b/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp
@@ -18,16 +18,35 @@
#define DBDICT_SCHEMA_FILE_HPP
#include <ndb_types.h>
+#include <ndb_version.h>
#include <string.h>
+#define NDB_SF_MAGIC "NDBSCHMA"
+
+// page size 4k
+#define NDB_SF_PAGE_SIZE_IN_WORDS_LOG2 10
+#define NDB_SF_PAGE_SIZE_IN_WORDS (1 << NDB_SF_PAGE_SIZE_IN_WORDS_LOG2)
+#define NDB_SF_PAGE_SIZE (NDB_SF_PAGE_SIZE_IN_WORDS << 2)
+
+// 4k = (1 + 127) * 32
+#define NDB_SF_PAGE_ENTRIES 127
+
+// 160 pages = 20320 objects
+#define NDB_SF_MAX_PAGES 160
+
+// versions where format changed
+#define NDB_SF_VERSION_5_0_6 MAKE_VERSION(5, 0, 6)
+
+// One page in schema file.
struct SchemaFile {
+ // header size 32 bytes
char Magic[8];
Uint32 ByteOrder;
Uint32 NdbVersion;
Uint32 FileSize; // In bytes
- Uint32 Unused;
-
- Uint32 CheckSum;
+ Uint32 PageNumber;
+ Uint32 CheckSum; // Of this page
+ Uint32 NoOfTableEntries; // On this page (NDB_SF_PAGE_ENTRIES)
enum TableState {
INIT = 0,
@@ -38,20 +57,33 @@ struct SchemaFile {
ALTER_TABLE_COMMITTED = 5
};
+ // entry size 32 bytes
struct TableEntry {
Uint32 m_tableState;
Uint32 m_tableVersion;
Uint32 m_tableType;
- Uint32 m_noOfPages;
+ Uint32 m_info_words;
Uint32 m_gcp;
+ Uint32 m_unused[3];
bool operator==(const TableEntry& o) const {
return memcmp(this, &o, sizeof(* this))== 0;
}
};
+
+ // pre-5.0.6
+ struct TableEntry_old {
+ Uint32 m_tableState;
+ Uint32 m_tableVersion;
+ Uint32 m_tableType;
+ Uint32 m_noOfPages;
+ Uint32 m_gcp;
+ };
- Uint32 NoOfTableEntries;
- TableEntry TableEntries[1];
+ union {
+ TableEntry TableEntries[NDB_SF_PAGE_ENTRIES];
+ TableEntry_old TableEntries_old[1];
+ };
};
#endif
diff --git a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
index a8b84298ebe..f73654fd9d5 100644
--- a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
+++ b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
@@ -16,19 +16,33 @@
#include <ndb_global.h>
+#include <ndb_version.h>
#include <NdbMain.h>
#include <NdbOut.hpp>
#include <SchemaFile.hpp>
-void
-usage(const char * prg){
- ndbout << "Usage " << prg
- << " P0.SchemaLog" << endl;
+static const char* progname = 0;
+static bool allflag = false;
+static bool checkonly = false;
+static bool equalcontents = false;
+static bool okquiet = false;
+
+static void
+usage()
+{
+ ndbout
+ << "Usage: " << progname << " [-aceq]" << " file ..." << endl
+ << "-a print also unused slots" << endl
+ << "-c check only (return status 1 on error)" << endl
+ << "-e check also that the files have identical contents" << endl
+ << "-q no output if file is ok" << endl
+ << "Example: " << progname << " -ceq ndb_*_fs/D[12]/DBDICT/P0.SchemaLog" << endl;
}
-void
-fill(const char * buf, int mod){
+static void
+fill(const char * buf, int mod)
+{
int len = strlen(buf)+1;
ndbout << buf << " ";
while((len % mod) != 0){
@@ -37,68 +51,222 @@ fill(const char * buf, int mod){
}
}
-void
-print(const char * filename, const SchemaFile * file){
- ndbout << "----- Schemafile: " << filename << " -----" << endl;
- ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %d FileSize: %d",
- sizeof(file->Magic), file->Magic,
- file->ByteOrder,
- file->NdbVersion,
- file->FileSize);
-
- for(Uint32 i = 0; i<file->NoOfTableEntries; i++){
- SchemaFile::TableEntry te = file->TableEntries[i];
- if(te.m_tableState != SchemaFile::INIT){
- ndbout << "Table " << i << ": State = " << te.m_tableState
- << " version = " << te.m_tableVersion
- << " type = " << te.m_tableType
- << " noOfPages = " << te.m_noOfPages
- << " gcp: " << te.m_gcp << endl;
- }
+static const char*
+version(Uint32 v)
+{
+ static char buf[40];
+ sprintf(buf, "%d.%d.%d", v >> 16, (v >> 8) & 0xFF, v & 0xFF);
+ return buf;
+}
+
+static int
+print_head(const char * filename, const SchemaFile * sf)
+{
+ int retcode = 0;
+
+ if (! checkonly) {
+ ndbout << "----- Schemafile: " << filename << " -----" << endl;
+ ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %s FileSize: %d",
+ sizeof(sf->Magic),
+ sf->Magic,
+ sf->ByteOrder,
+ version(sf->NdbVersion),
+ sf->FileSize);
}
+
+ if (memcmp(sf->Magic, "NDBSCHMA", sizeof(sf->Magic) != 0)) {
+ ndbout << filename << ": invalid header magic" << endl;
+ retcode = 1;
+ }
+
+ if ((sf->NdbVersion >> 16) < 4 || (sf->NdbVersion >> 16) > 9) {
+ ndbout << filename << ": impossible version " << hex << sf->NdbVersion << endl;
+ retcode = 1;
+ }
+
+ return retcode;
}
-NDB_COMMAND(printSchemafile,
- "printSchemafile", "printSchemafile", "Prints a schemafile", 16384){
- if(argc < 2){
- usage(argv[0]);
- return 0;
+static int
+print_old(const char * filename, const SchemaFile * sf, Uint32 sz)
+{
+ int retcode = 0;
+
+ if (print_head(filename, sf) != 0)
+ retcode = 1;
+
+ for (Uint32 i = 0; i < sf->NoOfTableEntries; i++) {
+ SchemaFile::TableEntry_old te = sf->TableEntries_old[i];
+ if (allflag ||
+ (te.m_tableState != SchemaFile::INIT &&
+ te.m_tableState != SchemaFile::DROP_TABLE_COMMITTED)) {
+ if (! checkonly)
+ ndbout << "Table " << i << ":"
+ << " State = " << te.m_tableState
+ << " version = " << te.m_tableVersion
+ << " type = " << te.m_tableType
+ << " noOfPages = " << te.m_noOfPages
+ << " gcp: " << te.m_gcp << endl;
+ }
}
+ return retcode;
+}
+
+static int
+print(const char * filename, const SchemaFile * xsf, Uint32 sz)
+{
+ int retcode = 0;
- const char * filename = argv[1];
+ if (print_head(filename, xsf) != 0)
+ retcode = 1;
- struct stat sbuf;
- const int res = stat(filename, &sbuf);
- if(res != 0){
- ndbout << "Could not find file: \"" << filename << "\"" << endl;
- return 0;
+ assert(sizeof(SchemaFile) == NDB_SF_PAGE_SIZE);
+ if (xsf->FileSize != sz || xsf->FileSize % NDB_SF_PAGE_SIZE != 0) {
+ ndbout << filename << ": invalid FileSize " << xsf->FileSize << endl;
+ retcode = 1;
}
- const Uint32 bytes = sbuf.st_size;
-
- Uint32 * buf = new Uint32[bytes/4+1];
-
- FILE * f = fopen(filename, "rb");
- if(f == 0){
- ndbout << "Failed to open file" << endl;
- delete [] buf;
- return 0;
+ Uint32 noOfPages = xsf->FileSize / NDB_SF_PAGE_SIZE;
+ for (Uint32 n = 0; n < noOfPages; n++) {
+ if (! checkonly) {
+ ndbout << "----- Page: " << n << " (" << noOfPages << ") -----" << endl;
+ }
+ const SchemaFile * sf = &xsf[n];
+ if (memcmp(sf->Magic, xsf->Magic, sizeof(sf->Magic)) != 0) {
+ ndbout << filename << ": page " << n << " invalid magic" << endl;
+ retcode = 1;
+ }
+ if (sf->FileSize != xsf->FileSize) {
+ ndbout << filename << ": page " << n << " FileSize changed to " << sf->FileSize << "!=" << xsf->FileSize << endl;
+ retcode = 1;
+ }
+ Uint32 cs = 0;
+ for (Uint32 j = 0; j < NDB_SF_PAGE_SIZE_IN_WORDS; j++)
+ cs ^= ((const Uint32*)sf)[j];
+ if (cs != 0) {
+ ndbout << filename << ": page " << n << " invalid CheckSum" << endl;
+ retcode = 1;
+ }
+ if (sf->NoOfTableEntries != NDB_SF_PAGE_ENTRIES) {
+ ndbout << filename << ": page " << n << " invalid NoOfTableEntries " << sf->NoOfTableEntries << endl;
+ retcode = 1;
+ }
+ for (Uint32 i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
+ SchemaFile::TableEntry te = sf->TableEntries[i];
+ Uint32 j = n * NDB_SF_PAGE_ENTRIES + i;
+ if (allflag ||
+ (te.m_tableState != SchemaFile::INIT &&
+ te.m_tableState != SchemaFile::DROP_TABLE_COMMITTED)) {
+ if (! checkonly)
+ ndbout << "Table " << j << ":"
+ << " State = " << te.m_tableState
+ << " version = " << te.m_tableVersion
+ << " type = " << te.m_tableType
+ << " noOfWords = " << te.m_info_words
+ << " gcp: " << te.m_gcp << endl;
+ }
+ if (te.m_unused[0] != 0 || te.m_unused[1] != 0 || te.m_unused[2] != 0) {
+ ndbout << filename << ": entry " << j << " garbage in m_unused[3]" << endl;
+ retcode = 1;
+ }
+ }
}
- Uint32 sz = fread(buf, 1, bytes, f);
- fclose(f);
- if(sz != bytes){
- ndbout << "Failure while reading file" << endl;
- delete [] buf;
- return 0;
+
+ return retcode;
+}
+
+NDB_COMMAND(printSchemafile,
+ "printSchemafile", "printSchemafile", "Prints a schemafile", 16384)
+{
+ progname = argv[0];
+ int exitcode = 0;
+
+ while (argc > 1 && argv[1][0] == '-') {
+ if (strchr(argv[1], 'a') != 0)
+ allflag = true;
+ if (strchr(argv[1], 'c') != 0)
+ checkonly = true;
+ if (strchr(argv[1], 'e') != 0)
+ equalcontents = true;
+ if (strchr(argv[1], 'q') != 0)
+ okquiet = true;
+ if (strchr(argv[1], 'h') != 0 || strchr(argv[1], '?') != 0) {
+ usage();
+ return 0;
+ }
+ argc--, argv++;
}
-
- print(filename, (SchemaFile *)&buf[0]);
- Uint32 chk = 0, i;
- for (i = 0; i < bytes/4; i++)
- chk ^= buf[i];
- if (chk != 0)
- ndbout << "Invalid checksum!" << endl;
+ const char * prevfilename = 0;
+ Uint32 * prevbuf = 0;
+ Uint32 prevbytes = 0;
+
+ while (argc > 1) {
+ const char * filename = argv[1];
+ argc--, argv++;
+
+ struct stat sbuf;
+ const int res = stat(filename, &sbuf);
+ if (res != 0) {
+ ndbout << filename << ": not found errno=" << errno << endl;
+ exitcode = 1;
+ continue;
+ }
+ const Uint32 bytes = sbuf.st_size;
+
+ Uint32 * buf = new Uint32[bytes/4+1];
+
+ FILE * f = fopen(filename, "rb");
+ if (f == 0) {
+ ndbout << filename << ": open failed errno=" << errno << endl;
+ delete [] buf;
+ exitcode = 1;
+ continue;
+ }
+ Uint32 sz = fread(buf, 1, bytes, f);
+ fclose(f);
+ if (sz != bytes) {
+ ndbout << filename << ": read failed errno=" << errno << endl;
+ delete [] buf;
+ exitcode = 1;
+ continue;
+ }
+
+ if (sz < 32) {
+ ndbout << filename << ": too short (no header)" << endl;
+ delete [] buf;
+ exitcode = 1;
+ continue;
+ }
+
+ SchemaFile* sf = (SchemaFile *)&buf[0];
+ int ret;
+ if (sf->NdbVersion < NDB_SF_VERSION_5_0_6)
+ ret = print_old(filename, sf, sz);
+ else
+ ret = print(filename, sf, sz);
+
+ if (ret != 0) {
+ ndbout << filename << ": check failed"
+ << " version=" << version(sf->NdbVersion) << endl;
+ exitcode = 1;
+ } else if (! okquiet) {
+ ndbout << filename << ": ok"
+ << " version=" << version(sf->NdbVersion) << endl;
+ }
+
+ if (equalcontents && prevfilename != 0) {
+ if (prevbytes != bytes || memcmp(prevbuf, buf, bytes) != 0) {
+ ndbout << filename << ": differs from " << prevfilename << endl;
+ exitcode = 1;
+ }
+ }
+
+ prevfilename = filename;
+ delete [] prevbuf;
+ prevbuf = buf;
+ prevbytes = bytes;
+ }
- delete [] buf;
- return 0;
+ delete [] prevbuf;
+ return exitcode;
}
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index 78acf1ffd19..5c2cfac5eb1 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -718,6 +718,9 @@ private:
void checkPrepDropTabComplete(Signal *, TabRecordPtr tabPtr);
void checkWaitDropTabFailedLqh(Signal *, Uint32 nodeId, Uint32 tableId);
+ void execDICT_LOCK_CONF(Signal* signal);
+ void execDICT_LOCK_REF(Signal* signal);
+
// Statement blocks
//------------------------------------
// Methods that send signals
@@ -935,6 +938,7 @@ private:
void initialStartCompletedLab(Signal *);
void allNodesLcpCompletedLab(Signal *);
void nodeRestartPh2Lab(Signal *);
+ void nodeRestartPh2Lab2(Signal *);
void initGciFilesLab(Signal *);
void dictStartConfLab(Signal *);
void nodeDictStartConfLab(Signal *);
@@ -1594,6 +1598,33 @@ private:
* Reply from nodeId
*/
void startInfoReply(Signal *, Uint32 nodeId);
+
+ // DIH specifics for execNODE_START_REP (sendDictUnlockOrd)
+ void exec_node_start_rep(Signal* signal);
+
+ /*
+ * Lock master DICT. Only current use is by starting node
+ * during NR. A pool of slave records is convenient anyway.
+ */
+ struct DictLockSlaveRecord {
+ Uint32 lockPtr;
+ Uint32 lockType;
+ bool locked;
+ Callback callback;
+ Uint32 nextPool;
+ };
+
+ typedef Ptr<DictLockSlaveRecord> DictLockSlavePtr;
+ ArrayPool<DictLockSlaveRecord> c_dictLockSlavePool;
+
+ // slave
+ void sendDictLockReq(Signal* signal, Uint32 lockType, Callback c);
+ void recvDictLockConf(Signal* signal);
+ void sendDictUnlockOrd(Signal* signal, Uint32 lockSlavePtrI);
+
+ // NR
+ Uint32 c_dictLockSlavePtrI_nodeRestart; // userPtr for NR
+ void recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret);
};
#if (DIH_CDATA_SIZE < _SYSFILE_SIZE32)
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
index 1c14163fe76..2b878034258 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihInit.cpp
@@ -66,11 +66,15 @@ void Dbdih::initData()
waitGCPProxyPool.setSize(ZPROXY_FILE_SIZE);
waitGCPMasterPool.setSize(ZPROXY_MASTER_FILE_SIZE);
+ c_dictLockSlavePool.setSize(1); // assert single usage
+ c_dictLockSlavePtrI_nodeRestart = RNIL;
+
cgcpOrderBlocked = 0;
c_lcpState.ctcCounter = 0;
cwaitLcpSr = false;
c_blockCommit = false;
c_blockCommitNo = 1;
+ cntrlblockref = RNIL;
}//Dbdih::initData()
void Dbdih::initRecords()
@@ -262,8 +266,21 @@ Dbdih::Dbdih(const class Configuration & config):
addRecSignal(GSN_CREATE_FRAGMENTATION_REQ,
&Dbdih::execCREATE_FRAGMENTATION_REQ);
-
- initData();
+
+ addRecSignal(GSN_DICT_LOCK_CONF, &Dbdih::execDICT_LOCK_CONF);
+ addRecSignal(GSN_DICT_LOCK_REF, &Dbdih::execDICT_LOCK_REF);
+
+ apiConnectRecord = 0;
+ connectRecord = 0;
+ fileRecord = 0;
+ fragmentstore = 0;
+ pageRecord = 0;
+ replicaRecord = 0;
+ tabRecord = 0;
+ createReplicaRecord = 0;
+ nodeGroupRecord = 0;
+ nodeRecord = 0;
+ takeOverRecord = 0;
}//Dbdih::Dbdih()
Dbdih::~Dbdih()
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 65c864bd853..4ca4e15111c 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -67,6 +67,7 @@
#include <signaldata/CreateFragmentation.hpp>
#include <signaldata/LqhFrag.hpp>
#include <signaldata/FsOpenReq.hpp>
+#include <signaldata/DictLock.hpp>
#include <DebuggerNames.hpp>
#include <EventLogger.hpp>
@@ -247,7 +248,7 @@ void Dbdih::sendSTART_RECREQ(Signal* signal, Uint32 nodeId)
req->newestGci = SYSFILE->newestRestorableGCI;
sendSignal(ref, GSN_START_RECREQ, signal, StartRecReq::SignalLength, JBB);
- signal->theData[0] = EventReport::StartREDOLog;
+ signal->theData[0] = NDB_LE_StartREDOLog;
signal->theData[1] = nodeId;
signal->theData[2] = SYSFILE->keepGCI;
signal->theData[3] = SYSFILE->lastCompletedGCI[nodeId];
@@ -544,7 +545,7 @@ void Dbdih::execCONTINUEB(Signal* signal)
break;
case DihContinueB::ZSTART_PERMREQ_AGAIN:
jam();
- nodeRestartPh2Lab(signal);
+ nodeRestartPh2Lab2(signal);
return;
break;
case DihContinueB::SwitchReplica:
@@ -1053,17 +1054,25 @@ void Dbdih::execREAD_CONFIG_REQ(Signal* signal)
const ndb_mgm_configuration_iterator * p =
theConfiguration.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_API_CONNECT,
- &capiConnectFileSize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_CONNECT,&cconnectFileSize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_FRAG_CONNECT,
- &cfragstoreFileSize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_REPLICAS,
- &creplicaFileSize));
- ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DIH_TABLE, &ctabFileSize))
- cfileFileSize = (2 * ctabFileSize) + 2;
+ ndbrequireErr(p != 0, NDBD_EXIT_INVALID_CONFIG);
+
+ initData();
+
+ ndbrequireErr(!ndb_mgm_get_int_parameter(p, CFG_DIH_API_CONNECT,
+ &capiConnectFileSize),
+ NDBD_EXIT_INVALID_CONFIG);
+ ndbrequireErr(!ndb_mgm_get_int_parameter(p, CFG_DIH_CONNECT,
+ &cconnectFileSize),
+ NDBD_EXIT_INVALID_CONFIG);
+ ndbrequireErr(!ndb_mgm_get_int_parameter(p, CFG_DIH_FRAG_CONNECT,
+ &cfragstoreFileSize),
+ NDBD_EXIT_INVALID_CONFIG);
+ ndbrequireErr(!ndb_mgm_get_int_parameter(p, CFG_DIH_REPLICAS,
+ &creplicaFileSize),
+ NDBD_EXIT_INVALID_CONFIG);
+ ndbrequireErr(!ndb_mgm_get_int_parameter(p, CFG_DIH_TABLE, &ctabFileSize),
+ NDBD_EXIT_INVALID_CONFIG);
+ cfileFileSize = (2 * ctabFileSize) + 2;
initRecords();
initialiseRecordsLab(signal, 0, ref, senderData);
return;
@@ -1276,6 +1285,7 @@ void Dbdih::execNDB_STTOR(Signal* signal)
case NodeState::ST_INITIAL_NODE_RESTART:
case NodeState::ST_NODE_RESTART:
jam();
+
/***********************************************************************
* When starting nodes while system is operational we must be controlled
* by the master since only one node restart is allowed at a time.
@@ -1286,7 +1296,7 @@ void Dbdih::execNDB_STTOR(Signal* signal)
req->startingRef = reference();
req->startingVersion = 0; // Obsolete
sendSignal(cmasterdihref, GSN_START_MEREQ, signal,
- StartMeReq::SignalLength, JBB);
+ StartMeReq::SignalLength, JBB);
return;
}
ndbrequire(false);
@@ -1354,6 +1364,27 @@ void Dbdih::execNDB_STTOR(Signal* signal)
}//Dbdih::execNDB_STTOR()
void
+Dbdih::exec_node_start_rep(Signal* signal)
+{
+ /*
+ * Send DICT_UNLOCK_ORD when this node is SL_STARTED.
+ *
+ * Sending it before (sp 7) conflicts with code which assumes
+ * SL_STARTING means we are in copy phase of NR.
+ *
+ * NodeState::starting.restartType is not supposed to be used
+ * when SL_STARTED. Also it seems NODE_START_REP can arrive twice.
+ *
+ * For these reasons there are no consistency checks and
+ * we rely on c_dictLockSlavePtrI_nodeRestart alone.
+ */
+ if (c_dictLockSlavePtrI_nodeRestart != RNIL) {
+ sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart);
+ c_dictLockSlavePtrI_nodeRestart = RNIL;
+ }
+}
+
+void
Dbdih::createMutexes(Signal * signal, Uint32 count){
Callback c = { safe_cast(&Dbdih::createMutex_done), count };
@@ -1494,9 +1525,7 @@ void Dbdih::execREAD_NODESCONF(Signal* signal)
"Illegal configuration change."
" Initial start needs to be performed "
" when changing no of storage nodes (node %d)", i);
- progError(__LINE__,
- ERR_INVALID_CONFIG,
- buf);
+ progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf);
}
}
@@ -1558,6 +1587,35 @@ void Dbdih::execREAD_NODESCONF(Signal* signal)
/*---------------------------------------------------------------------------*/
void Dbdih::nodeRestartPh2Lab(Signal* signal)
{
+ /*
+ * Lock master DICT to avoid metadata operations during INR/NR.
+ * Done just before START_PERMREQ.
+ *
+ * It would be more elegant to do this just before START_MEREQ.
+ * The problem is, on INR we end up in massive invalidateNodeLCP
+ * which is not fully protected against metadata ops.
+ */
+ ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL);
+
+ // check that we are not yet taking part in schema ops
+ CRASH_INSERTION(7174);
+
+ Uint32 lockType = DictLockReq::NodeRestartLock;
+ Callback c = { safe_cast(&Dbdih::recvDictLockConf_nodeRestart), 0 };
+ sendDictLockReq(signal, lockType, c);
+}
+
+void Dbdih::recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret)
+{
+ ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL);
+ ndbrequire(data != RNIL);
+ c_dictLockSlavePtrI_nodeRestart = data;
+
+ nodeRestartPh2Lab2(signal);
+}
+
+void Dbdih::nodeRestartPh2Lab2(Signal* signal)
+{
/*------------------------------------------------------------------------*/
// REQUEST FOR PERMISSION FROM MASTER TO START A NODE IN AN ALREADY
// RUNNING SYSTEM.
@@ -1568,7 +1626,7 @@ void Dbdih::nodeRestartPh2Lab(Signal* signal)
req->nodeId = cownNodeId;
req->startType = cstarttype;
sendSignal(cmasterdihref, GSN_START_PERMREQ, signal, 3, JBB);
-}//Dbdih::nodeRestartPh2Lab()
+}
void Dbdih::execSTART_PERMCONF(Signal* signal)
{
@@ -1604,7 +1662,7 @@ void Dbdih::execSTART_PERMREF(Signal* signal)
" with --initial as partial start has been performed"
" and this filesystem is unusable");
progError(__LINE__,
- ERR_SR_RESTARTCONFLICT,
+ NDBD_EXIT_SR_RESTARTCONFLICT,
buf);
ndbrequire(false);
}
@@ -1690,12 +1748,12 @@ void Dbdih::execSTART_PERMREQ(Signal* signal)
const BlockReference retRef = req->blockRef;
const Uint32 nodeId = req->nodeId;
const Uint32 typeStart = req->startType;
-
CRASH_INSERTION(7122);
ndbrequire(isMaster());
ndbrequire(refToNode(retRef) == nodeId);
if ((c_nodeStartMaster.activeState) ||
- (c_nodeStartMaster.wait != ZFALSE)) {
+ (c_nodeStartMaster.wait != ZFALSE) ||
+ ERROR_INSERTED_CLEAR(7175)) {
jam();
signal->theData[0] = nodeId;
signal->theData[1] = StartPermRef::ZNODE_ALREADY_STARTING_ERROR;
@@ -1868,7 +1926,7 @@ void Dbdih::nodeDictStartConfLab(Signal* signal)
/*-----------------------------------------------------------------*/
// Report that node restart has completed copy of dictionary.
/*-----------------------------------------------------------------*/
- signal->theData[0] = EventReport::NR_CopyDict;
+ signal->theData[0] = NDB_LE_NR_CopyDict;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
}//Dbdih::nodeDictStartConfLab()
@@ -1889,7 +1947,7 @@ void Dbdih::gcpBlockedLab(Signal* signal)
/*-----------------------------------------------------------------*/
// Report that node restart has completed copy of distribution info.
/*-----------------------------------------------------------------*/
- signal->theData[0] = EventReport::NR_CopyDistr;
+ signal->theData[0] = NDB_LE_NR_CopyDistr;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
/**
@@ -1964,9 +2022,6 @@ void Dbdih::execINCL_NODECONF(Signal* signal)
signal->theData[0] = reference();
signal->theData[1] = c_nodeStartSlave.nodeId;
sendSignal(BACKUP_REF, GSN_INCL_NODEREQ, signal, 2, JBB);
-
- // Suma will not send response to this for now, later...
- sendSignal(SUMA_REF, GSN_INCL_NODEREQ, signal, 2, JBB);
return;
}//if
if (TstartNode_or_blockref == numberToRef(BACKUP, getOwnNodeId())){
@@ -2050,7 +2105,7 @@ void Dbdih::execSTART_COPYREQ(Signal* signal)
/*-------------------------------------------------------------------------*/
// REPORT Copy process of node restart is now about to start up.
/*-------------------------------------------------------------------------*/
- signal->theData[0] = EventReport::NR_CopyFragsStarted;
+ signal->theData[0] = NDB_LE_NR_CopyFragsStarted;
signal->theData[1] = startNodeId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -3031,7 +3086,7 @@ void Dbdih::execCREATE_FRAGCONF(Signal* signal)
/* --------------------------------------------------------------------- */
// REPORT that copy of fragment has been completed.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NR_CopyFragDone;
+ signal->theData[0] = NDB_LE_NR_CopyFragDone;
signal->theData[1] = takeOverPtr.p->toStartingNode;
signal->theData[2] = tabPtr.i;
signal->theData[3] = takeOverPtr.p->toCurrentFragid;
@@ -3269,7 +3324,7 @@ Dbdih::switchPrimaryMutex_locked(Signal* signal, Uint32 toPtrI, Uint32 retVal){
void Dbdih::toCopyCompletedLab(Signal * signal, TakeOverRecordPtr takeOverPtr)
{
- signal->theData[0] = EventReport::NR_CopyFragsCompleted;
+ signal->theData[0] = NDB_LE_NR_CopyFragsCompleted;
signal->theData[1] = takeOverPtr.p->toStartingNode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -3593,9 +3648,7 @@ void Dbdih::selectMasterCandidateAndSend(Signal* signal)
" Initial start needs to be performed "
" when changing no of replicas (%d != %d)",
node_groups[nodePtr.i], cnoReplicas);
- progError(__LINE__,
- ERR_INVALID_CONFIG,
- buf);
+ progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf);
}
}
}//Dbdih::selectMasterCandidate()
@@ -3802,6 +3855,11 @@ void Dbdih::execNODE_FAILREP(Signal* signal)
/*------------------------------------------------------------------------*/
// Verify that a starting node has also crashed. Reset the node start record.
/*-------------------------------------------------------------------------*/
+#if 0
+ /**
+ * Node will crash by itself...
+ * nodeRestart is run then...
+ */
if (false && c_nodeStartMaster.startNode != RNIL && getNodeStatus(c_nodeStartMaster.startNode) == NodeRecord::ALIVE)
{
BlockReference cntrRef = calcNdbCntrBlockRef(c_nodeStartMaster.startNode);
@@ -3813,6 +3871,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal)
sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA);
nodeResetStart();
}//if
+#endif
/*--------------------------------------------------*/
/* */
@@ -3884,9 +3943,7 @@ void Dbdih::execNODE_FAILREP(Signal* signal)
if(getNodeState().getNodeRestartInProgress()){
jam();
- progError(__LINE__,
- ERR_SYSTEM_ERROR,
- "Unhandle master failure during node restart");
+ progError(__LINE__, NDBD_EXIT_MASTER_FAILURE_DURING_NR);
}
}
@@ -4550,7 +4607,7 @@ void Dbdih::startGcpMasterTakeOver(Signal* signal, Uint32 oldMasterId){
sendLoopMacro(MASTER_GCPREQ, sendMASTER_GCPREQ);
cgcpMasterTakeOverState = GMTOS_INITIAL;
- signal->theData[0] = EventReport::GCP_TakeoverStarted;
+ signal->theData[0] = NDB_LE_GCP_TakeoverStarted;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
setLocalNodefailHandling(signal, oldMasterId, NF_GCP_TAKE_OVER);
@@ -5059,7 +5116,7 @@ void Dbdih::MASTER_GCPhandling(Signal* signal, Uint32 failedNodeId)
break;
}//switch
- signal->theData[0] = EventReport::GCP_TakeoverCompleted;
+ signal->theData[0] = NDB_LE_GCP_TakeoverCompleted;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
/*--------------------------------------------------*/
@@ -5509,7 +5566,7 @@ Dbdih::checkEmptyLcpComplete(Signal *signal){
if(isMaster()){
jam();
- signal->theData[0] = EventReport::LCP_TakeoverStarted;
+ signal->theData[0] = NDB_LE_LCP_TakeoverStarted;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
signal->theData[0] = 7012;
@@ -5981,7 +6038,7 @@ void Dbdih::MASTER_LCPhandling(Signal* signal, Uint32 failedNodeId)
ndbrequire(false);
break;
}//switch
- signal->theData[0] = EventReport::LCP_TakeoverCompleted;
+ signal->theData[0] = NDB_LE_LCP_TakeoverCompleted;
signal->theData[1] = c_lcpMasterTakeOverState.state;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -6013,7 +6070,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* -------------------------------------------------------------------- */
// Report the event that DBTC completed node failure handling.
/* -------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBTC;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -6026,7 +6083,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* --------------------------------------------------------------------- */
// Report the event that DBDICT completed node failure handling.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBDICT;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -6039,7 +6096,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* --------------------------------------------------------------------- */
// Report the event that DBDIH completed node failure handling.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBDIH;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -6052,7 +6109,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* --------------------------------------------------------------------- */
// Report the event that DBDIH completed node failure handling.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = DBLQH;
signal->theData[2] = failedNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -6087,7 +6144,7 @@ void Dbdih::execNF_COMPLETEREP(Signal* signal)
/* -------------------------------------------------------------------- */
// Report the event that nodeId has completed node failure handling.
/* -------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = 0;
signal->theData[2] = failedNodePtr.i;
signal->theData[3] = nodeId;
@@ -6160,7 +6217,7 @@ void Dbdih::nodeFailCompletedCheckLab(Signal* signal,
/* ---------------------------------------------------------------------- */
// Report the event that all nodes completed node failure handling.
/* ---------------------------------------------------------------------- */
- signal->theData[0] = EventReport::NodeFailCompleted;
+ signal->theData[0] = NDB_LE_NodeFailCompleted;
signal->theData[1] = 0;
signal->theData[2] = failedNodePtr.i;
signal->theData[3] = 0;
@@ -6315,9 +6372,12 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
if (primaryTableId == RNIL) {
if(fragmentNode == 0){
jam();
- // needs to be fixed for single fragment tables
- NGPtr.i = 0; //c_nextNodeGroup;
- c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
+ NGPtr.i = 0;
+ if(noOfFragments < csystemnodes)
+ {
+ NGPtr.i = c_nextNodeGroup;
+ c_nextNodeGroup = (NGPtr.i + 1 == cnoOfNodeGroups ? 0 : NGPtr.i + 1);
+ }
} else if(! (fragmentNode < MAX_NDB_NODES)) {
jam();
err = CreateFragmentationRef::InvalidNodeId;
@@ -6370,33 +6430,28 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
}
}
- //@todo use section writer
Uint32 count = 2;
- Uint32 fragments[2 + 8*MAX_REPLICAS*MAX_NDB_NODES];
- Uint32 next_replica_node[MAX_NDB_NODES];
- memset(next_replica_node,0,sizeof(next_replica_node));
+ Uint16 *fragments = (Uint16*)(signal->theData+25);
if (primaryTableId == RNIL) {
jam();
+ Uint8 next_replica_node[MAX_NDB_NODES];
+ memset(next_replica_node,0,sizeof(next_replica_node));
for(Uint32 fragNo = 0; fragNo<noOfFragments; fragNo++){
jam();
ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
-
- Uint32 ind = next_replica_node[NGPtr.i];
const Uint32 max = NGPtr.p->nodeCount;
-
- //-------------------------------------------------------------------
- // We make an extra step to ensure that the primary replicas are
- // spread among the nodes.
- //-------------------------------------------------------------------
- next_replica_node[NGPtr.i] = (ind + 1 >= max ? 0 : ind + 1);
-
- for(Uint32 replicaNo = 0; replicaNo<noOfReplicas; replicaNo++){
+
+ Uint32 tmp= next_replica_node[NGPtr.i];
+ for(Uint32 replicaNo = 0; replicaNo<noOfReplicas; replicaNo++)
+ {
jam();
- const Uint32 nodeId = NGPtr.p->nodesInGroup[ind++];
+ const Uint32 nodeId = NGPtr.p->nodesInGroup[tmp++];
fragments[count++] = nodeId;
- ind = (ind == max ? 0 : ind);
+ tmp = (tmp >= max ? 0 : tmp);
}
-
+ tmp++;
+ next_replica_node[NGPtr.i]= (tmp >= max ? 0 : tmp);
+
/**
* Next node group for next fragment
*/
@@ -6445,26 +6500,42 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
fragments[0] = noOfReplicas;
fragments[1] = noOfFragments;
- LinearSectionPtr ptr[3];
- ptr[0].p = &fragments[0];
- ptr[0].sz = count;
- sendSignal(senderRef,
- GSN_CREATE_FRAGMENTATION_CONF,
- signal,
- CreateFragmentationConf::SignalLength,
- JBB,
- ptr,
- 1);
+ if(senderRef != 0)
+ {
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)&fragments[0];
+ ptr[0].sz = (count + 1) / 2;
+ sendSignal(senderRef,
+ GSN_CREATE_FRAGMENTATION_CONF,
+ signal,
+ CreateFragmentationConf::SignalLength,
+ JBB,
+ ptr,
+ 1);
+ }
+ else
+ {
+ // Execute direct
+ signal->theData[0] = 0;
+ }
return;
} while(false);
-
- CreateFragmentationRef * const ref =
- (CreateFragmentationRef*)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->senderData = senderData;
- ref->errorCode = err;
- sendSignal(senderRef, GSN_CREATE_FRAGMENTATION_REF, signal,
- CreateFragmentationRef::SignalLength, JBB);
+
+ if(senderRef != 0)
+ {
+ CreateFragmentationRef * const ref =
+ (CreateFragmentationRef*)signal->getDataPtrSend();
+ ref->senderRef = reference();
+ ref->senderData = senderData;
+ ref->errorCode = err;
+ sendSignal(senderRef, GSN_CREATE_FRAGMENTATION_REF, signal,
+ CreateFragmentationRef::SignalLength, JBB);
+ }
+ else
+ {
+ // Execute direct
+ signal->theData[0] = err;
+ }
}
void Dbdih::execDIADDTABREQ(Signal* signal)
@@ -6532,12 +6603,15 @@ void Dbdih::execDIADDTABREQ(Signal* signal)
tabPtr.p->method = TabRecord::HASH;
tabPtr.p->kvalue = req->kValue;
- Uint32 fragments[2 + 8*MAX_REPLICAS*MAX_NDB_NODES];
+ union {
+ Uint16 fragments[2 + MAX_FRAG_PER_NODE*MAX_REPLICAS*MAX_NDB_NODES];
+ Uint32 align;
+ };
SegmentedSectionPtr fragDataPtr;
signal->getSection(fragDataPtr, DiAddTabReq::FRAGMENTATION);
- copy(fragments, fragDataPtr);
+ copy((Uint32*)fragments, fragDataPtr);
releaseSections(signal);
-
+
const Uint32 noReplicas = fragments[0];
const Uint32 noFragments = fragments[1];
@@ -6546,6 +6620,7 @@ void Dbdih::execDIADDTABREQ(Signal* signal)
ndbrequire(noReplicas == cnoReplicas); // Only allowed
if (ERROR_INSERTED(7173)) {
+ CLEAR_ERROR_INSERT_VALUE;
addtabrefuseLab(signal, connectPtr, ZREPLERROR1);
return;
}
@@ -6965,8 +7040,7 @@ void Dbdih::execDIGETNODESREQ(Signal* signal)
TabRecord* regTabDesc = tabRecord;
jamEntry();
ptrCheckGuard(tabPtr, ttabFileSize, regTabDesc);
- hashValue = hashValue >> tabPtr.p->kvalue;
- Uint32 fragId = tabPtr.p->mask & hashValue;
+ Uint32 fragId = hashValue & tabPtr.p->mask;
ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
if (fragId < tabPtr.p->hashpointer) {
jam();
@@ -7327,7 +7401,7 @@ void Dbdih::startGcpLab(Signal* signal, Uint32 aWaitTime)
/***************************************************************************/
// Report the event that a global checkpoint has started.
/***************************************************************************/
- signal->theData[0] = EventReport::GlobalCheckpointStarted; //Event type
+ signal->theData[0] = NDB_LE_GlobalCheckpointStarted; //Event type
signal->theData[1] = cnewgcp;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -7590,6 +7664,22 @@ void Dbdih::execDIHNDBTAMPER(Signal* signal)
#ifdef ERROR_INSERT
case 5:
jam();
+ if(tuserpointer == 0)
+ {
+ jam();
+ signal->theData[0] = 0;
+ sendSignal(QMGR_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(NDBCNTR_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(NDBFS_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBACC_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBTUP_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBLQH_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBDICT_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBDIH_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(DBTC_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ sendSignal(CMVMI_REF, GSN_NDB_TAMPER, signal, 1, JBB);
+ return;
+ }
/*----------------------------------------------------------------------*/
// Insert errors.
/*----------------------------------------------------------------------*/
@@ -7808,7 +7898,7 @@ void Dbdih::execCOPY_GCICONF(Signal* signal)
// Report the event that a global checkpoint has completed.
/************************************************************************/
signal->setTrace(0);
- signal->theData[0] = EventReport::GlobalCheckpointCompleted; //Event type
+ signal->theData[0] = NDB_LE_GlobalCheckpointCompleted; //Event type
signal->theData[1] = coldgcp;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -7930,12 +8020,6 @@ void Dbdih::writingCopyGciLab(Signal* signal, FileRecordPtr filePtr)
if (reason == CopyGCIReq::GLOBAL_CHECKPOINT) {
jam();
cgcpParticipantState = GCP_PARTICIPANT_READY;
-
- SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr();
- rep->gci = coldgcp;
- rep->senderData = 0;
- sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength, JBB);
}
jam();
@@ -8168,11 +8252,21 @@ void Dbdih::openingTableErrorLab(Signal* signal, FileRecordPtr filePtr)
/* WE FAILED IN OPENING A FILE. IF THE FIRST FILE THEN TRY WITH THE */
/* DUPLICATE FILE, OTHERWISE WE REPORT AN ERROR IN THE SYSTEM RESTART. */
/* ---------------------------------------------------------------------- */
- ndbrequire(filePtr.i == tabPtr.p->tabFile[0]);
- filePtr.i = tabPtr.p->tabFile[1];
- ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
- openFileRw(signal, filePtr);
- filePtr.p->reqStatus = FileRecord::OPENING_TABLE;
+ if (filePtr.i == tabPtr.p->tabFile[0])
+ {
+ filePtr.i = tabPtr.p->tabFile[1];
+ ptrCheckGuard(filePtr, cfileFileSize, fileRecord);
+ openFileRw(signal, filePtr);
+ filePtr.p->reqStatus = FileRecord::OPENING_TABLE;
+ }
+ else
+ {
+ char buf[256];
+ BaseString::snprintf(buf, sizeof(buf),
+ "Error opening DIH schema files for table: %d",
+ tabPtr.i);
+ progError(__LINE__, NDBD_EXIT_AFS_NO_SUCH_FILE, buf);
+ }
}//Dbdih::openingTableErrorLab()
void Dbdih::readingTableLab(Signal* signal, FileRecordPtr filePtr)
@@ -8294,7 +8388,7 @@ Dbdih::resetReplicaSr(TabRecordPtr tabPtr){
/* --------------------------------------------------------------- */
/* THE NODE IS ALIVE AND KICKING AND ACTIVE, LET'S USE IT. */
/* --------------------------------------------------------------- */
- arrGuard(noCrashedReplicas, 8);
+ arrGuardErr(noCrashedReplicas, 8, NDBD_EXIT_MAX_CRASHED_REPLICAS);
Uint32 lastGci = replicaPtr.p->replicaLastGci[noCrashedReplicas];
if(lastGci >= newestRestorableGCI){
jam();
@@ -8313,7 +8407,7 @@ Dbdih::resetReplicaSr(TabRecordPtr tabPtr){
*--------_----------------------------------------------------- */
const Uint32 nextCrashed = noCrashedReplicas + 1;
replicaPtr.p->noCrashedReplicas = nextCrashed;
- arrGuard(nextCrashed, 8);
+ arrGuardErr(nextCrashed, 8, NDBD_EXIT_MAX_CRASHED_REPLICAS);
replicaPtr.p->createGci[nextCrashed] = newestRestorableGCI + 1;
ndbrequire(newestRestorableGCI + 1 != 0xF1F1F1F1);
replicaPtr.p->replicaLastGci[nextCrashed] = (Uint32)-1;
@@ -8768,14 +8862,10 @@ void Dbdih::startFragment(Signal* signal, Uint32 tableId, Uint32 fragId)
/* THIS WILL DECREASE THE GCI TO RESTORE WHICH HOPEFULLY WILL MAKE IT */
/* POSSIBLE TO RESTORE THE SYSTEM. */
/* --------------------------------------------------------------------- */
- char buf[100];
- BaseString::snprintf(buf, sizeof(buf),
- "Unable to find restorable replica for "
- "table: %d fragment: %d gci: %d",
- tableId, fragId, SYSFILE->newestRestorableGCI);
- progError(__LINE__,
- ERR_SYSTEM_ERROR,
- buf);
+ char buf[64];
+ BaseString::snprintf(buf, sizeof(buf), "table: %d fragment: %d gci: %d",
+ tableId, fragId, SYSFILE->newestRestorableGCI);
+ progError(__LINE__, NDBD_EXIT_NO_RESTORABLE_REPLICA, buf);
ndbrequire(false);
return;
}//if
@@ -9312,7 +9402,7 @@ void Dbdih::execTCGETOPSIZECONF(Signal* signal)
ndbrequire(((int)c_lcpState.oldestRestorableGci) > 0);
if (ERROR_INSERTED(7011)) {
- signal->theData[0] = EventReport::LCPStoppedInCalcKeepGci;
+ signal->theData[0] = NDB_LE_LCPStoppedInCalcKeepGci;
signal->theData[1] = 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
return;
@@ -9398,7 +9488,7 @@ void Dbdih::storeNewLcpIdLab(Signal* signal)
/***************************************************************************/
// Report the event that a local checkpoint has started.
/***************************************************************************/
- signal->theData[0] = EventReport::LocalCheckpointStarted; //Event type
+ signal->theData[0] = NDB_LE_LocalCheckpointStarted; //Event type
signal->theData[1] = SYSFILE->latestLCP_ID + 1;
signal->theData[2] = c_lcpState.keepGci;
signal->theData[3] = c_lcpState.oldestRestorableGci;
@@ -9778,7 +9868,7 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal)
/* --------------------------------------------------------------------- */
// REPORT that local checkpoint have completed this fragment.
/* --------------------------------------------------------------------- */
- signal->theData[0] = EventReport::LCPFragmentCompleted;
+ signal->theData[0] = NDB_LE_LCPFragmentCompleted;
signal->theData[1] = nodeId;
signal->theData[2] = tableId;
signal->theData[3] = fragId;
@@ -10229,7 +10319,7 @@ void Dbdih::allNodesLcpCompletedLab(Signal* signal)
/***************************************************************************/
// Report the event that a local checkpoint has completed.
/***************************************************************************/
- signal->theData[0] = EventReport::LocalCheckpointCompleted; //Event type
+ signal->theData[0] = NDB_LE_LocalCheckpointCompleted; //Event type
signal->theData[1] = SYSFILE->latestLCP_ID;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
c_lcpState.lcpStopGcp = c_newest_restorable_gci;
@@ -10387,7 +10477,91 @@ void Dbdih::tableCloseLab(Signal* signal, FileRecordPtr filePtr)
* GCP stop detected,
* send SYSTEM_ERROR to all other alive nodes
*/
-void Dbdih::crashSystemAtGcpStop(Signal* signal){
+void Dbdih::crashSystemAtGcpStop(Signal* signal)
+{
+ switch(cgcpStatus){
+ case GCP_NODE_FINISHED:
+ {
+ /**
+ * We're waiting for a GCP save conf
+ */
+ ndbrequire(!c_GCP_SAVEREQ_Counter.done());
+ NodeReceiverGroup rg(DBLQH, c_GCP_SAVEREQ_Counter);
+ signal->theData[0] = 2305;
+ sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
+
+ infoEvent("Detected GCP stop...sending kill to %s",
+ c_GCP_SAVEREQ_Counter.getText());
+ ndbout_c("Detected GCP stop...sending kill to %s",
+ c_GCP_SAVEREQ_Counter.getText());
+ return;
+ }
+ case GCP_SAVE_LQH_FINISHED:
+ ndbout_c("m_copyReason: %d m_waiting: %d",
+ c_copyGCIMaster.m_copyReason,
+ c_copyGCIMaster.m_waiting);
+ break;
+ case GCP_READY: // shut up lint
+ case GCP_PREPARE_SENT:
+ case GCP_COMMIT_SENT:
+ break;
+ }
+
+ ndbout_c("c_copyGCISlave: sender{Data, Ref} %d %x reason: %d nextWord: %d",
+ c_copyGCISlave.m_senderData,
+ c_copyGCISlave.m_senderRef,
+ c_copyGCISlave.m_copyReason,
+ c_copyGCISlave.m_expectedNextWord);
+
+ FileRecordPtr file0Ptr;
+ file0Ptr.i = crestartInfoFile[0];
+ ptrCheckGuard(file0Ptr, cfileFileSize, fileRecord);
+ FileRecordPtr file1Ptr;
+ file1Ptr.i = crestartInfoFile[1];
+ ptrCheckGuard(file1Ptr, cfileFileSize, fileRecord);
+
+ ndbout_c("file[0] status: %d type: %d reqStatus: %d file1: %d %d %d",
+ file0Ptr.p->fileStatus, file0Ptr.p->fileType, file0Ptr.p->reqStatus,
+ file1Ptr.p->fileStatus, file1Ptr.p->fileType, file1Ptr.p->reqStatus
+ );
+
+ signal->theData[0] = 404;
+ signal->theData[1] = file0Ptr.p->fileRef;
+ EXECUTE_DIRECT(NDBFS, GSN_DUMP_STATE_ORD, signal, 2);
+
+ signal->theData[0] = 404;
+ signal->theData[1] = file1Ptr.p->fileRef;
+ EXECUTE_DIRECT(NDBFS, GSN_DUMP_STATE_ORD, signal, 2);
+
+ ndbout_c("c_COPY_GCIREQ_Counter = %s",
+ c_COPY_GCIREQ_Counter.getText());
+ ndbout_c("c_COPY_TABREQ_Counter = %s",
+ c_COPY_TABREQ_Counter.getText());
+ ndbout_c("c_CREATE_FRAGREQ_Counter = %s",
+ c_CREATE_FRAGREQ_Counter.getText());
+ ndbout_c("c_DIH_SWITCH_REPLICA_REQ_Counter = %s",
+ c_DIH_SWITCH_REPLICA_REQ_Counter.getText());
+ ndbout_c("c_EMPTY_LCP_REQ_Counter = %s",c_EMPTY_LCP_REQ_Counter.getText());
+ ndbout_c("c_END_TOREQ_Counter = %s", c_END_TOREQ_Counter.getText());
+ ndbout_c("c_GCP_COMMIT_Counter = %s", c_GCP_COMMIT_Counter.getText());
+ ndbout_c("c_GCP_PREPARE_Counter = %s", c_GCP_PREPARE_Counter.getText());
+ ndbout_c("c_GCP_SAVEREQ_Counter = %s", c_GCP_SAVEREQ_Counter.getText());
+ ndbout_c("c_INCL_NODEREQ_Counter = %s", c_INCL_NODEREQ_Counter.getText());
+ ndbout_c("c_MASTER_GCPREQ_Counter = %s",
+ c_MASTER_GCPREQ_Counter.getText());
+ ndbout_c("c_MASTER_LCPREQ_Counter = %s",
+ c_MASTER_LCPREQ_Counter.getText());
+ ndbout_c("c_START_INFOREQ_Counter = %s",
+ c_START_INFOREQ_Counter.getText());
+ ndbout_c("c_START_RECREQ_Counter = %s", c_START_RECREQ_Counter.getText());
+ ndbout_c("c_START_TOREQ_Counter = %s", c_START_TOREQ_Counter.getText());
+ ndbout_c("c_STOP_ME_REQ_Counter = %s", c_STOP_ME_REQ_Counter.getText());
+ ndbout_c("c_TC_CLOPSIZEREQ_Counter = %s",
+ c_TC_CLOPSIZEREQ_Counter.getText());
+ ndbout_c("c_TCGETOPSIZEREQ_Counter = %s",
+ c_TCGETOPSIZEREQ_Counter.getText());
+ ndbout_c("c_UPDATE_TOREQ_Counter = %s", c_UPDATE_TOREQ_Counter.getText());
+
NodeRecordPtr nodePtr;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam();
@@ -10543,7 +10717,7 @@ void Dbdih::calculateHotSpare()
break;
default:
jam();
- progError(0, 0);
+ ndbrequire(false);
break;
}//switch
}//Dbdih::calculateHotSpare()
@@ -10576,7 +10750,7 @@ void Dbdih::checkEscalation()
jam();
if (TnodeGroup[i] == ZFALSE) {
jam();
- progError(__LINE__, ERR_SYSTEM_ERROR, "Lost node group");
+ progError(__LINE__, NDBD_EXIT_LOST_NODE_GROUP, "Lost node group");
}//if
}//for
}//Dbdih::checkEscalation()
@@ -11086,7 +11260,7 @@ void Dbdih::initCommonData()
ndb_mgm_get_int_parameter(p, CFG_DB_NO_REPLICAS, &cnoReplicas);
if (cnoReplicas > 4)
{
- progError(__LINE__, ERR_INVALID_CONFIG,
+ progError(__LINE__, NDBD_EXIT_INVALID_CONFIG,
"Only up to four replicas are supported. Check NoOfReplicas.");
}
@@ -11565,16 +11739,14 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
NodeRecordPtr mngNodeptr;
Uint32 tmngNode;
Uint32 tmngNodeGroup;
- Uint32 tmngReplica;
Uint32 tmngLimit;
- Uint32 i;
+ Uint32 i, j;
/**-----------------------------------------------------------------------
* ASSIGN ALL ACTIVE NODES INTO NODE GROUPS. HOT SPARE NODES ARE ASSIGNED
* TO NODE GROUP ZNIL
*-----------------------------------------------------------------------*/
tmngNodeGroup = 0;
- tmngReplica = 0;
tmngLimit = csystemnodes - cnoHotSpare;
ndbrequire(tmngLimit < MAX_NDB_NODES);
for (i = 0; i < tmngLimit; i++) {
@@ -11586,13 +11758,11 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
mngNodeptr.p->nodeGroup = tmngNodeGroup;
NGPtr.i = tmngNodeGroup;
ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
- arrGuard(tmngReplica, MAX_REPLICAS);
- NGPtr.p->nodesInGroup[tmngReplica] = mngNodeptr.i;
- tmngReplica++;
- if (tmngReplica == cnoReplicas) {
+ arrGuard(NGPtr.p->nodeCount, MAX_REPLICAS);
+ NGPtr.p->nodesInGroup[NGPtr.p->nodeCount++] = mngNodeptr.i;
+ if (NGPtr.p->nodeCount == cnoReplicas) {
jam();
tmngNodeGroup++;
- tmngReplica = 0;
}//if
}//for
cnoOfNodeGroups = tmngNodeGroup;
@@ -11616,6 +11786,38 @@ void Dbdih::makeNodeGroups(Uint32 nodeArray[])
Sysfile::setNodeGroup(mngNodeptr.i, SYSFILE->nodeGroups, mngNodeptr.p->nodeGroup);
}//if
}//for
+
+ for (i = 0; i<cnoOfNodeGroups; i++)
+ {
+ jam();
+ bool alive = false;
+ NodeGroupRecordPtr NGPtr;
+ NGPtr.i = i;
+ ptrCheckGuard(NGPtr, MAX_NDB_NODES, nodeGroupRecord);
+ for (j = 0; j<NGPtr.p->nodeCount; j++)
+ {
+ jam();
+ mngNodeptr.i = NGPtr.p->nodesInGroup[j];
+ ptrCheckGuard(mngNodeptr, MAX_NDB_NODES, nodeRecord);
+ if (checkNodeAlive(NGPtr.p->nodesInGroup[j]))
+ {
+ alive = true;
+ break;
+ }
+ }
+
+ if (!alive)
+ {
+ char buf[255];
+ BaseString::snprintf
+ (buf, sizeof(buf),
+ "Illegal initial start, no alive node in nodegroup %u", i);
+ progError(__LINE__,
+ NDBD_EXIT_SR_RESTARTCONFLICT,
+ buf);
+
+ }
+ }
}//Dbdih::makeNodeGroups()
/**
@@ -11751,7 +11953,8 @@ void Dbdih::newCrashedReplica(Uint32 nodeId, ReplicaRecordPtr ncrReplicaPtr)
/* THAT THE NEW REPLICA IS NOT STARTED YET AND REPLICA_LAST_GCI IS*/
/* SET TO -1 TO INDICATE THAT IT IS NOT DEAD YET. */
/*----------------------------------------------------------------------*/
- arrGuard(ncrReplicaPtr.p->noCrashedReplicas + 1, 8);
+ arrGuardErr(ncrReplicaPtr.p->noCrashedReplicas + 1, 8,
+ NDBD_EXIT_MAX_CRASHED_REPLICAS);
ncrReplicaPtr.p->replicaLastGci[ncrReplicaPtr.p->noCrashedReplicas] =
SYSFILE->lastCompletedGCI[nodeId];
ncrReplicaPtr.p->noCrashedReplicas = ncrReplicaPtr.p->noCrashedReplicas + 1;
@@ -12423,7 +12626,6 @@ void Dbdih::sendStartFragreq(Signal* signal,
void Dbdih::setInitialActiveStatus()
{
NodeRecordPtr siaNodeptr;
- Uint32 tsiaNodeActiveStatus;
Uint32 tsiaNoActiveNodes;
tsiaNoActiveNodes = csystemnodes - cnoHotSpare;
@@ -12431,39 +12633,34 @@ void Dbdih::setInitialActiveStatus()
SYSFILE->nodeStatus[i] = 0;
for (siaNodeptr.i = 1; siaNodeptr.i < MAX_NDB_NODES; siaNodeptr.i++) {
ptrAss(siaNodeptr, nodeRecord);
- if (siaNodeptr.p->nodeStatus == NodeRecord::ALIVE) {
+ switch(siaNodeptr.p->nodeStatus){
+ case NodeRecord::ALIVE:
+ case NodeRecord::DEAD:
if (tsiaNoActiveNodes == 0) {
jam();
siaNodeptr.p->activeStatus = Sysfile::NS_HotSpare;
} else {
jam();
tsiaNoActiveNodes = tsiaNoActiveNodes - 1;
- siaNodeptr.p->activeStatus = Sysfile::NS_Active;
- }//if
- } else {
- jam();
- siaNodeptr.p->activeStatus = Sysfile::NS_NotDefined;
- }//if
- switch (siaNodeptr.p->activeStatus) {
- case Sysfile::NS_Active:
- jam();
- tsiaNodeActiveStatus = Sysfile::NS_Active;
- break;
- case Sysfile::NS_HotSpare:
- jam();
- tsiaNodeActiveStatus = Sysfile::NS_HotSpare;
- break;
- case Sysfile::NS_NotDefined:
- jam();
- tsiaNodeActiveStatus = Sysfile::NS_NotDefined;
+ if (siaNodeptr.p->nodeStatus == NodeRecord::ALIVE)
+ {
+ jam();
+ siaNodeptr.p->activeStatus = Sysfile::NS_Active;
+ }
+ else
+ {
+ siaNodeptr.p->activeStatus = Sysfile::NS_NotActive_NotTakenOver;
+ }
+ }
break;
default:
- ndbrequire(false);
- return;
+ jam();
+ siaNodeptr.p->activeStatus = Sysfile::NS_NotDefined;
break;
- }//switch
- Sysfile::setNodeStatus(siaNodeptr.i, SYSFILE->nodeStatus,
- tsiaNodeActiveStatus);
+ }//if
+ Sysfile::setNodeStatus(siaNodeptr.i,
+ SYSFILE->nodeStatus,
+ siaNodeptr.p->activeStatus);
}//for
}//Dbdih::setInitialActiveStatus()
@@ -14499,3 +14696,118 @@ Dbdih::NodeRecord::NodeRecord(){
copyCompleted = false;
allowNodeStart = true;
}
+
+// DICT lock slave
+
+void
+Dbdih::sendDictLockReq(Signal* signal, Uint32 lockType, Callback c)
+{
+ DictLockReq* req = (DictLockReq*)&signal->theData[0];
+ DictLockSlavePtr lockPtr;
+
+ c_dictLockSlavePool.seize(lockPtr);
+ ndbrequire(lockPtr.i != RNIL);
+
+ req->userPtr = lockPtr.i;
+ req->lockType = lockType;
+ req->userRef = reference();
+
+ lockPtr.p->lockPtr = RNIL;
+ lockPtr.p->lockType = lockType;
+ lockPtr.p->locked = false;
+ lockPtr.p->callback = c;
+
+ // handle rolling upgrade
+ {
+ Uint32 masterVersion = getNodeInfo(cmasterNodeId).m_version;
+
+ unsigned int get_major = getMajor(masterVersion);
+ unsigned int get_minor = getMinor(masterVersion);
+ unsigned int get_build = getBuild(masterVersion);
+
+ ndbrequire(get_major == 4 || get_major == 5);
+
+ if (masterVersion < NDBD_DICT_LOCK_VERSION_5 ||
+ ERROR_INSERTED(7176)) {
+ jam();
+
+ infoEvent("DIH: detect upgrade: master node %u old version %u.%u.%u",
+ (unsigned int)cmasterNodeId, get_major, get_minor, get_build);
+
+ DictLockConf* conf = (DictLockConf*)&signal->theData[0];
+ conf->userPtr = lockPtr.i;
+ conf->lockType = lockType;
+ conf->lockPtr = ZNIL;
+
+ sendSignal(reference(), GSN_DICT_LOCK_CONF, signal,
+ DictLockConf::SignalLength, JBB);
+ return;
+ }
+ }
+
+ BlockReference dictMasterRef = calcDictBlockRef(cmasterNodeId);
+ sendSignal(dictMasterRef, GSN_DICT_LOCK_REQ, signal,
+ DictLockReq::SignalLength, JBB);
+}
+
+void
+Dbdih::execDICT_LOCK_CONF(Signal* signal)
+{
+ jamEntry();
+ recvDictLockConf(signal);
+}
+
+void
+Dbdih::execDICT_LOCK_REF(Signal* signal)
+{
+ jamEntry();
+ ndbrequire(false);
+}
+
+void
+Dbdih::recvDictLockConf(Signal* signal)
+{
+ const DictLockConf* conf = (const DictLockConf*)&signal->theData[0];
+
+ DictLockSlavePtr lockPtr;
+ c_dictLockSlavePool.getPtr(lockPtr, conf->userPtr);
+
+ lockPtr.p->lockPtr = conf->lockPtr;
+ ndbrequire(lockPtr.p->lockType == conf->lockType);
+ ndbrequire(lockPtr.p->locked == false);
+ lockPtr.p->locked = true;
+
+ lockPtr.p->callback.m_callbackData = lockPtr.i;
+ execute(signal, lockPtr.p->callback, 0);
+}
+
+void
+Dbdih::sendDictUnlockOrd(Signal* signal, Uint32 lockSlavePtrI)
+{
+ DictUnlockOrd* ord = (DictUnlockOrd*)&signal->theData[0];
+
+ DictLockSlavePtr lockPtr;
+ c_dictLockSlavePool.getPtr(lockPtr, lockSlavePtrI);
+
+ ord->lockPtr = lockPtr.p->lockPtr;
+ ord->lockType = lockPtr.p->lockType;
+
+ c_dictLockSlavePool.release(lockPtr);
+
+ // handle rolling upgrade
+ {
+ Uint32 masterVersion = getNodeInfo(cmasterNodeId).m_version;
+
+ unsigned int get_major = getMajor(masterVersion);
+ ndbrequire(get_major == 4 || get_major == 5);
+
+ if (masterVersion < NDBD_DICT_LOCK_VERSION_5 ||
+ ERROR_INSERTED(7176)) {
+ return;
+ }
+ }
+
+ BlockReference dictMasterRef = calcDictBlockRef(cmasterNodeId);
+ sendSignal(dictMasterRef, GSN_DICT_UNLOCK_ORD, signal,
+ DictUnlockOrd::SignalLength, JBB);
+}
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index 7cca121d909..d3ba8521226 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -29,6 +29,9 @@
#include <signaldata/LqhTransConf.hpp>
#include <signaldata/LqhFrag.hpp>
+// primary key is stored in TUP
+#include <../dbtup/Dbtup.hpp>
+
#ifdef DBLQH_C
// Constants
/* ------------------------------------------------------------------------- */
@@ -441,7 +444,6 @@ public:
UintR dictConnectptr;
UintR fragmentPtr;
UintR nextAddfragrec;
- UintR noOfAllocPages;
UintR schemaVer;
UintR tup1Connectptr;
UintR tup2Connectptr;
@@ -463,12 +465,17 @@ public:
Uint16 totalAttrReceived;
Uint16 fragCopyCreation;
Uint16 noOfKeyAttr;
- Uint32 noOfNewAttr; // noOfCharsets in upper half
+ Uint16 noOfNewAttr;
+ Uint16 noOfCharsets;
Uint16 noOfAttributeGroups;
Uint16 lh3DistrBits;
Uint16 tableType;
Uint16 primaryTableId;
- };// Size 108 bytes
+ Uint32 maxRowsLow;
+ Uint32 maxRowsHigh;
+ Uint32 minRowsLow;
+ Uint32 minRowsHigh;
+ };// Size 124 bytes
typedef Ptr<AddFragRecord> AddFragRecordPtr;
/* $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ */
@@ -512,9 +519,7 @@ public:
WAIT_DELETE_STORED_PROC_ID_COPY = 6,
WAIT_ACC_COPY = 7,
WAIT_ACC_SCAN = 8,
- WAIT_SCAN_KEYINFO = 9,
WAIT_SCAN_NEXTREQ = 10,
- WAIT_COPY_KEYINFO = 11,
WAIT_CLOSE_SCAN = 12,
WAIT_CLOSE_COPY = 13,
WAIT_RELEASE_LOCK = 14,
@@ -576,6 +581,9 @@ public:
NodeId scanNodeId;
Uint16 scanReleaseCounter;
Uint16 scanNumber;
+
+ // scan source block ACC TUX TUP
+ BlockReference scanBlockref;
Uint8 scanCompletedStatus;
Uint8 scanFlag;
@@ -583,6 +591,8 @@ public:
Uint8 scanLockMode;
Uint8 readCommitted;
Uint8 rangeScan;
+ Uint8 descending;
+ Uint8 tupScan;
Uint8 scanTcWaiting;
Uint8 scanKeyinfoFlag;
Uint8 m_last_row;
@@ -879,10 +889,6 @@ public:
*/
Uint8 fragDistributionKey;
/**
- * Used to calculate which local fragment to use.
- */
- Uint8 hashCheckBit;
- /**
* The identity of the next local checkpoint this fragment
* should perform.
*/
@@ -2022,8 +2028,10 @@ public:
BlockReference tcTuxBlockref;
BlockReference tcTupBlockref;
Uint32 commitAckMarker;
- UintR noFiredTriggers;
-
+ union {
+ Uint32 m_scan_curr_range_no;
+ UintR noFiredTriggers;
+ };
Uint16 errorCode;
Uint16 logStartPageIndex;
Uint16 logStartPageNo;
@@ -2045,6 +2053,7 @@ public:
Uint8 opExec;
Uint8 operation;
Uint8 reclenAiLqhkey;
+ Uint8 m_offset_current_keybuf;
Uint8 replicaType;
Uint8 simpleRead;
Uint8 seqNoReplica;
@@ -2148,8 +2157,6 @@ private:
void execACC_SCANREF(Signal* signal);
void execNEXT_SCANCONF(Signal* signal);
void execNEXT_SCANREF(Signal* signal);
- void execACC_SCAN_INFO(Signal* signal);
- void execACC_SCAN_INFO24(Signal* signal);
void execACC_TO_REF(Signal* signal);
void execSTORED_PROCCONF(Signal* signal);
void execSTORED_PROCREF(Signal* signal);
@@ -2239,7 +2246,7 @@ private:
void LQHKEY_abort(Signal* signal, int errortype);
void LQHKEY_error(Signal* signal, int errortype);
void nextRecordCopy(Signal* signal);
- void calculateHash(Signal* signal);
+ Uint32 calculateHash(Uint32 tableId, const Uint32* src);
void continueAfterCheckLcpStopBlocked(Signal* signal);
void checkLcpStopBlockedLab(Signal* signal);
void sendCommittedTc(Signal* signal, BlockReference atcBlockref);
@@ -2267,7 +2274,7 @@ private:
void finishScanrec(Signal* signal);
void releaseScanrec(Signal* signal);
void seizeScanrec(Signal* signal);
- void sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
+ Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
void sendScanFragConf(Signal* signal, Uint32 scanCompleted);
void initCopyrec(Signal* signal);
void initCopyTc(Signal* signal);
@@ -2397,6 +2404,8 @@ private:
void seizeAttrinbuf(Signal* signal);
Uint32 seize_attrinbuf();
Uint32 release_attrinbuf(Uint32);
+ Uint32 copy_bounds(Uint32 * dst, TcConnectionrec*);
+
void seizeFragmentrec(Signal* signal);
void seizePageRef(Signal* signal);
void seizeTcrec();
@@ -2408,7 +2417,7 @@ private:
void startNextExecSr(Signal* signal);
void startTimeSupervision(Signal* signal);
void stepAhead(Signal* signal, Uint32 stepAheadWords);
- void systemError(Signal* signal);
+ void systemError(Signal* signal, int line);
void writeAbortLog(Signal* signal);
void writeCommitLog(Signal* signal, LogPartRecordPtr regLogPartPtr);
void writeCompletedGciLog(Signal* signal);
@@ -2427,7 +2436,7 @@ private:
Uint32 calcPageCheckSum(LogPageRecordPtr logP);
// Generated statement blocks
- void systemErrorLab(Signal* signal);
+ void systemErrorLab(Signal* signal, int line);
void initFourth(Signal* signal);
void packLqhkeyreqLab(Signal* signal);
void sendNdbSttorryLab(Signal* signal);
@@ -2437,7 +2446,6 @@ private:
void srLogLimits(Signal* signal);
void srGciLimits(Signal* signal);
void srPhase3Start(Signal* signal);
- void warningHandlerLab(Signal* signal);
void checkStartCompletedLab(Signal* signal);
void continueAbortLab(Signal* signal);
void abortContinueAfterBlockedLab(Signal* signal, bool canBlock);
@@ -2445,7 +2453,6 @@ private:
void localCommitLab(Signal* signal);
void abortErrorLab(Signal* signal);
void continueAfterReceivingAllAiLab(Signal* signal);
- void sendScanFragRefLateLab(Signal* signal);
void abortStateHandlerLab(Signal* signal);
void writeAttrinfoLab(Signal* signal);
void scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
@@ -2512,7 +2519,7 @@ private:
void nextScanConfScanLab(Signal* signal);
void nextScanConfCopyLab(Signal* signal);
void continueScanNextReqLab(Signal* signal);
- bool keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
+ void keyinfoLab(const Uint32 * src, const Uint32 * end);
void copySendTupkeyReqLab(Signal* signal);
void storedProcConfScanLab(Signal* signal);
void storedProcConfCopyLab(Signal* signal);
@@ -2568,7 +2575,6 @@ private:
void accScanConfScanLab(Signal* signal);
void accScanConfCopyLab(Signal* signal);
void scanLockReleasedLab(Signal* signal);
- void accScanInfoEnterLab(Signal* signal, Uint32* dataPtr, Uint32 length);
void openSrFourthNextLab(Signal* signal);
void closingInitLab(Signal* signal);
void closeExecSrCompletedLab(Signal* signal);
@@ -2583,6 +2589,8 @@ private:
void initData();
void initRecords();
+ Dbtup* c_tup;
+ Uint32 readPrimaryKeys(ScanRecord*, TcConnectionrec*, Uint32 * dst);
// ----------------------------------------------------------------
// These are variables handling the records. For most records one
// pointer to the array of structs, one pointer-struct, a file size
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index f9dd63e782d..04400f75255 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -273,8 +273,6 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_ACC_SCANREF, &Dblqh::execACC_SCANREF);
addRecSignal(GSN_NEXT_SCANCONF, &Dblqh::execNEXT_SCANCONF);
addRecSignal(GSN_NEXT_SCANREF, &Dblqh::execNEXT_SCANREF);
- addRecSignal(GSN_ACC_SCAN_INFO, &Dblqh::execACC_SCAN_INFO);
- addRecSignal(GSN_ACC_SCAN_INFO24, &Dblqh::execACC_SCAN_INFO24);
addRecSignal(GSN_STORED_PROCCONF, &Dblqh::execSTORED_PROCCONF);
addRecSignal(GSN_STORED_PROCREF, &Dblqh::execSTORED_PROCREF);
addRecSignal(GSN_COPY_FRAGREQ, &Dblqh::execCOPY_FRAGREQ);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index e4289715c38..87f2849aebc 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -55,6 +55,7 @@
#include <signaldata/AlterTab.hpp>
#include <signaldata/LCP.hpp>
+#include <KeyDescriptor.hpp>
// Use DEBUG to print messages that should be
// seen only when we debug the product
@@ -167,9 +168,11 @@ void Dblqh::execTUP_COM_UNBLOCK(Signal* signal)
/* ------- SEND SYSTEM ERROR ------- */
/* */
/* ------------------------------------------------------------------------- */
-void Dblqh::systemError(Signal* signal)
+void Dblqh::systemError(Signal* signal, int line)
{
- progError(0, 0);
+ signal->theData[0] = 2304;
+ execDUMP_STATE_ORD(signal);
+ progError(line, NDBD_EXIT_NDBREQUIRE);
}//Dblqh::systemError()
/* *************** */
@@ -420,7 +423,7 @@ void Dblqh::execCONTINUEB(Signal* signal)
// Report information about transaction activity once per second.
/* --------------------------------------------------------------------- */
if (signal->theData[1] == 0) {
- signal->theData[0] = EventReport::OperationReportCounters;
+ signal->theData[0] = NDB_LE_OperationReportCounters;
signal->theData[1] = c_Counters.operations;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}//if
@@ -517,6 +520,8 @@ void Dblqh::execSTTOR(Signal* signal)
jam();
cstartPhase = tstartPhase;
sttorStartphase1Lab(signal);
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
return;
break;
default:
@@ -961,12 +966,16 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
Uint8 tlh = req->lh3PageBits;
Uint32 tnoOfAttr = req->noOfAttributes;
Uint32 tnoOfNull = req->noOfNullAttributes;
- Uint32 noOfAlloc = req->noOfPagesToPreAllocate;
+ Uint32 maxRowsLow = req->maxRowsLow;
+ Uint32 maxRowsHigh = req->maxRowsHigh;
+ Uint32 minRowsLow = req->minRowsLow;
+ Uint32 minRowsHigh = req->minRowsHigh;
Uint32 tschemaVersion = req->schemaVersion;
Uint32 ttupKeyLength = req->keyLength;
Uint32 nextLcp = req->nextLCP;
Uint32 noOfKeyAttr = req->noOfKeyAttr;
Uint32 noOfNewAttr = req->noOfNewAttr;
+ Uint32 noOfCharsets = req->noOfCharsets;
Uint32 checksumIndicator = req->checksumIndicator;
Uint32 noOfAttributeGroups = req->noOfAttributeGroups;
Uint32 gcpIndicator = req->GCPIndicator;
@@ -1064,7 +1073,10 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
addfragptr.p->m_senderAttrPtr = RNIL;
addfragptr.p->noOfAttr = tnoOfAttr;
addfragptr.p->noOfNull = tnoOfNull;
- addfragptr.p->noOfAllocPages = noOfAlloc;
+ addfragptr.p->maxRowsLow = maxRowsLow;
+ addfragptr.p->maxRowsHigh = maxRowsHigh;
+ addfragptr.p->minRowsLow = minRowsLow;
+ addfragptr.p->minRowsHigh = minRowsHigh;
addfragptr.p->tabId = tabptr.i;
addfragptr.p->totalAttrReceived = 0;
addfragptr.p->attrSentToTup = ZNIL;/* TO FIND PROGRAMMING ERRORS QUICKLY */
@@ -1074,6 +1086,7 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
addfragptr.p->addfragErrorCode = 0;
addfragptr.p->noOfKeyAttr = noOfKeyAttr;
addfragptr.p->noOfNewAttr = noOfNewAttr;
+ addfragptr.p->noOfCharsets = noOfCharsets;
addfragptr.p->checksumIndicator = checksumIndicator;
addfragptr.p->noOfAttributeGroups = noOfAttributeGroups;
addfragptr.p->GCPIndicator = gcpIndicator;
@@ -1114,8 +1127,8 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
if (DictTabInfo::isOrderedIndex(tableType)) {
jam();
// NOTE: next 2 lines stolen from ACC
- addfragptr.p->fragid1 = (0 << tlhstar) | fragId;
- addfragptr.p->fragid2 = (1 << tlhstar) | fragId;
+ addfragptr.p->fragid1 = (fragId << 1) | 0;
+ addfragptr.p->fragid2 = (fragId << 1) | 1;
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
sendAddFragReq(signal);
return;
@@ -1135,7 +1148,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
Uint32 fragId2 = signal->theData[3];
Uint32 accFragPtr1 = signal->theData[4];
Uint32 accFragPtr2 = signal->theData[5];
- Uint32 hashCheckBit = signal->theData[6];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
@@ -1146,7 +1158,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
fragptr.p->accFragptr[0] = accFragPtr1;
fragptr.p->accFragptr[1] = accFragPtr2;
- fragptr.p->hashCheckBit = hashCheckBit;
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
sendAddFragReq(signal);
@@ -1245,47 +1256,56 @@ Dblqh::sendAddFragReq(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
if (addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUP ||
addfragptr.p->addfragStatus == AddFragRecord::WAIT_ONE_TUP) {
+ TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
if (DictTabInfo::isTable(addfragptr.p->tableType) ||
DictTabInfo::isHashIndex(addfragptr.p->tableType)) {
jam();
- signal->theData[0] = addfragptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = 0; /* ADD TABLE */
- signal->theData[3] = addfragptr.p->tabId;
- signal->theData[4] = addfragptr.p->noOfAttr;
- signal->theData[5] =
+ tupFragReq->userPtr = addfragptr.i;
+ tupFragReq->userRef = cownref;
+ tupFragReq->reqInfo = 0; /* ADD TABLE */
+ tupFragReq->tableId = addfragptr.p->tabId;
+ tupFragReq->noOfAttr = addfragptr.p->noOfAttr;
+ tupFragReq->fragId =
addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUP
? addfragptr.p->fragid1 : addfragptr.p->fragid2;
- signal->theData[6] = (addfragptr.p->noOfAllocPages >> 1) + 1;
- signal->theData[7] = addfragptr.p->noOfNull;
- signal->theData[8] = addfragptr.p->schemaVer;
- signal->theData[9] = addfragptr.p->noOfKeyAttr;
- signal->theData[10] = addfragptr.p->noOfNewAttr;
- signal->theData[11] = addfragptr.p->checksumIndicator;
- signal->theData[12] = addfragptr.p->noOfAttributeGroups;
- signal->theData[13] = addfragptr.p->GCPIndicator;
+ tupFragReq->maxRowsLow = addfragptr.p->maxRowsLow;
+ tupFragReq->maxRowsHigh = addfragptr.p->maxRowsHigh;
+ tupFragReq->minRowsLow = addfragptr.p->minRowsLow;
+ tupFragReq->minRowsHigh = addfragptr.p->minRowsHigh;
+ tupFragReq->noOfNullAttr = addfragptr.p->noOfNull;
+ tupFragReq->schemaVersion = addfragptr.p->schemaVer;
+ tupFragReq->noOfKeyAttr = addfragptr.p->noOfKeyAttr;
+ tupFragReq->noOfNewAttr = addfragptr.p->noOfNewAttr;
+ tupFragReq->noOfCharsets = addfragptr.p->noOfCharsets;
+ tupFragReq->checksumIndicator = addfragptr.p->checksumIndicator;
+ tupFragReq->noOfAttributeGroups = addfragptr.p->noOfAttributeGroups;
+ tupFragReq->globalCheckpointIdIndicator = addfragptr.p->GCPIndicator;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
signal, TupFragReq::SignalLength, JBB);
return;
}
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
jam();
- signal->theData[0] = addfragptr.i;
- signal->theData[1] = cownref;
- signal->theData[2] = 0; /* ADD TABLE */
- signal->theData[3] = addfragptr.p->tabId;
- signal->theData[4] = 1; /* ordered index: one array attr */
- signal->theData[5] =
+ tupFragReq->userPtr = addfragptr.i;
+ tupFragReq->userRef = cownref;
+ tupFragReq->reqInfo = 0; /* ADD TABLE */
+ tupFragReq->tableId = addfragptr.p->tabId;
+ tupFragReq->noOfAttr = 1; /* ordered index: one array attr */
+ tupFragReq->fragId =
addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUP
? addfragptr.p->fragid1 : addfragptr.p->fragid2;
- signal->theData[6] = (addfragptr.p->noOfAllocPages >> 1) + 1;
- signal->theData[7] = 0; /* ordered index: no nullable */
- signal->theData[8] = addfragptr.p->schemaVer;
- signal->theData[9] = 1; /* ordered index: one key */
- signal->theData[10] = addfragptr.p->noOfNewAttr;
- signal->theData[11] = addfragptr.p->checksumIndicator;
- signal->theData[12] = addfragptr.p->noOfAttributeGroups;
- signal->theData[13] = addfragptr.p->GCPIndicator;
+ tupFragReq->maxRowsLow = addfragptr.p->maxRowsLow;
+ tupFragReq->maxRowsHigh = addfragptr.p->maxRowsHigh;
+ tupFragReq->minRowsLow = addfragptr.p->minRowsLow;
+ tupFragReq->minRowsHigh = addfragptr.p->minRowsHigh;
+ tupFragReq->noOfNullAttr = 0; /* ordered index: no nullable */
+ tupFragReq->schemaVersion = addfragptr.p->schemaVer;
+ tupFragReq->noOfKeyAttr = 1; /* ordered index: one key */
+ tupFragReq->noOfNewAttr = addfragptr.p->noOfNewAttr;
+ tupFragReq->noOfCharsets = addfragptr.p->noOfCharsets;
+ tupFragReq->checksumIndicator = addfragptr.p->checksumIndicator;
+ tupFragReq->noOfAttributeGroups = addfragptr.p->noOfAttributeGroups;
+ tupFragReq->globalCheckpointIdIndicator = addfragptr.p->GCPIndicator;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ,
signal, TupFragReq::SignalLength, JBB);
return;
@@ -1304,7 +1324,7 @@ Dblqh::sendAddFragReq(Signal* signal)
tuxreq->noOfAttr = addfragptr.p->noOfAttr - 1; /* skip NDB$TNODE */
tuxreq->fragId =
addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX
- ? addfragptr.p->fragid1 : addfragptr.p->fragid2;
+ ? addfragptr.p->fragid1: addfragptr.p->fragid2;
tuxreq->fragOff = addfragptr.p->lh3DistrBits;
tuxreq->tableType = addfragptr.p->tableType;
tuxreq->primaryTableId = addfragptr.p->primaryTableId;
@@ -1604,28 +1624,35 @@ void Dblqh::abortAddFragOps(Signal* signal)
{
fragptr.i = addfragptr.p->fragmentPtr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- signal->theData[0] = (Uint32)-1;
if (addfragptr.p->tup1Connectptr != RNIL) {
jam();
- signal->theData[1] = addfragptr.p->tup1Connectptr;
+ TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
+ tupFragReq->userPtr = (Uint32)-1;
+ tupFragReq->userRef = addfragptr.p->tup1Connectptr;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
addfragptr.p->tup1Connectptr = RNIL;
}
if (addfragptr.p->tup2Connectptr != RNIL) {
jam();
- signal->theData[1] = addfragptr.p->tup2Connectptr;
+ TupFragReq* const tupFragReq = (TupFragReq*)signal->getDataPtrSend();
+ tupFragReq->userPtr = (Uint32)-1;
+ tupFragReq->userRef = addfragptr.p->tup2Connectptr;
sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
addfragptr.p->tup2Connectptr = RNIL;
}
if (addfragptr.p->tux1Connectptr != RNIL) {
jam();
- signal->theData[1] = addfragptr.p->tux1Connectptr;
+ TuxFragReq* const tuxFragReq = (TuxFragReq*)signal->getDataPtrSend();
+ tuxFragReq->userPtr = (Uint32)-1;
+ tuxFragReq->userRef = addfragptr.p->tux1Connectptr;
sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
addfragptr.p->tux1Connectptr = RNIL;
}
if (addfragptr.p->tux2Connectptr != RNIL) {
jam();
- signal->theData[1] = addfragptr.p->tux2Connectptr;
+ TuxFragReq* const tuxFragReq = (TuxFragReq*)signal->getDataPtrSend();
+ tuxFragReq->userPtr = (Uint32)-1;
+ tuxFragReq->userRef = addfragptr.p->tux2Connectptr;
sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
addfragptr.p->tux2Connectptr = RNIL;
}
@@ -2102,7 +2129,7 @@ void Dblqh::execTIME_SIGNAL(Signal* signal)
if ((cCounterAccCommitBlocked > 0) ||
(cCounterTupCommitBlocked > 0)) {
jam();
- signal->theData[0] = EventReport::UndoLogBlocked;
+ signal->theData[0] = NDB_LE_UndoLogBlocked;
signal->theData[1] = cCounterTupCommitBlocked;
signal->theData[2] = cCounterAccCommitBlocked;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -2646,12 +2673,20 @@ Dblqh::execREAD_PSUEDO_REQ(Signal* signal){
regTcPtr.i = signal->theData[0];
ptrCheckGuard(regTcPtr, ctcConnectrecFileSize, tcConnectionrec);
- FragrecordPtr regFragptr;
- regFragptr.i = regTcPtr.p->fragmentptr;
- ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
-
- signal->theData[0] = regFragptr.p->accFragptr[regTcPtr.p->localFragptr];
- EXECUTE_DIRECT(DBACC, GSN_READ_PSUEDO_REQ, signal, 2);
+ if(signal->theData[1] != AttributeHeader::RANGE_NO)
+ {
+ jam();
+ FragrecordPtr regFragptr;
+ regFragptr.i = regTcPtr.p->fragmentptr;
+ ptrCheckGuard(regFragptr, cfragrecFileSize, fragrecord);
+
+ signal->theData[0] = regFragptr.p->accFragptr[regTcPtr.p->localFragptr];
+ EXECUTE_DIRECT(DBACC, GSN_READ_PSUEDO_REQ, signal, 2);
+ }
+ else
+ {
+ signal->theData[0] = regTcPtr.p->m_scan_curr_range_no;
+ }
}
/* ************>> */
@@ -2666,11 +2701,11 @@ void Dblqh::execTUPKEYCONF(Signal* signal)
jamEntry();
tcConnectptr.i = tcIndex;
ptrCheckGuard(tcConnectptr, ttcConnectrecFileSize, regTcConnectionrec);
- if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
- tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
switch (tcConnectptr.p->transactionState) {
case TcConnectionrec::WAIT_TUP:
jam();
+ if (tcConnectptr.p->seqNoReplica == 0) // Primary replica
+ tcConnectptr.p->noFiredTriggers = tupKeyConf->noFiredTriggers;
tupkeyConfLab(signal);
break;
case TcConnectionrec::COPY_TUPKEY:
@@ -3552,7 +3587,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
LQHKEY_error(signal, 6);
return;
}//if
- regTcPtr->localFragptr = (regTcPtr->hashValue >> fragptr.p->hashCheckBit) & 1;
+ regTcPtr->localFragptr = regTcPtr->hashValue & 1;
Uint8 TcopyType = fragptr.p->fragCopy;
tfragDistKey = fragptr.p->fragDistributionKey;
if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
@@ -5137,7 +5172,7 @@ void Dblqh::errorReport(Signal* signal, int place)
jam();
break;
}//switch
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dblqh::errorReport()
@@ -5198,7 +5233,7 @@ void Dblqh::execCOMMITREQ(Signal* signal)
Uint32 transid2 = signal->theData[4];
Uint32 tcOprec = signal->theData[6];
if (ERROR_INSERTED(5004)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}
if (ERROR_INSERTED(5017)) {
CLEAR_ERROR_INSERT_VALUE;
@@ -5320,7 +5355,7 @@ void Dblqh::execCOMPLETEREQ(Signal* signal)
Uint32 transid2 = signal->theData[3];
Uint32 tcOprec = signal->theData[5];
if (ERROR_INSERTED(5005)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}
if (ERROR_INSERTED(5018)) {
CLEAR_ERROR_INSERT_VALUE;
@@ -5958,7 +5993,7 @@ void Dblqh::execABORTREQ(Signal* signal)
Uint32 transid2 = signal->theData[3];
Uint32 tcOprec = signal->theData[5];
if (ERROR_INSERTED(5006)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}
if (ERROR_INSERTED(5016)) {
CLEAR_ERROR_INSERT_VALUE;
@@ -6769,7 +6804,7 @@ void Dblqh::lqhTransNextLab(Signal* signal)
/* ------------------------------------------------------------
* THIS IS AN ERROR THAT SHOULD NOT OCCUR. WE CRASH THE SYSTEM.
* ------------------------------------------------------------ */
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
}//if
@@ -6872,49 +6907,6 @@ Dblqh::scanMarkers(Signal* signal,
* ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
* TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
* ------------------------------------------------------------------------- */
-
-void Dblqh::execACC_SCAN_INFO(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- Uint32 length = signal->theData[3];
- ndbrequire(length <= 4);
- accScanInfoEnterLab(signal, &signal->theData[4], length);
-}//Dblqh::execACC_SCAN_INFO()
-
-
-void Dblqh::execACC_SCAN_INFO24(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- Uint32 length = signal->theData[3];
- ndbrequire(length <= 20);
- accScanInfoEnterLab(signal, &signal->theData[4], length);
-}//Dblqh::execACC_SCAN_INFO24()
-
-void Dblqh::accScanInfoEnterLab(Signal* signal,
- Uint32* dataPtr,
- Uint32 length)
-{
- ndbrequire(length != 0);
- if (scanptr.p->scanState == ScanRecord::WAIT_SCAN_KEYINFO) {
- jam();
- if (keyinfoLab(signal, dataPtr, length)) {
- jam();
- nextScanConfLoopLab(signal);
- }//if
- } else {
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_COPY_KEYINFO);
- jam();
- if (keyinfoLab(signal, dataPtr, length)) {
- jam();
- copySendTupkeyReqLab(signal);
- }//if
- }//if
-}//Dblqh::accScanInfoEnterLab()
-
/* *************** */
/* ACC_SCANCONF > */
/* *************** */
@@ -6989,7 +6981,7 @@ void Dblqh::execNEXT_SCANCONF(Signal* signal)
void Dblqh::execNEXT_SCANREF(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dblqh::execNEXT_SCANREF()
@@ -7044,6 +7036,7 @@ void Dblqh::execSTORED_PROCREF(Signal* signal)
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_STORED_PROC_SCAN:
jam();
+ scanptr.p->scanCompletedStatus = ZTRUE;
scanptr.p->scanStoredProcId = signal->theData[2];
tcConnectptr.p->errorCode = errorCode;
closeScanLab(signal);
@@ -7249,10 +7242,7 @@ void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal)
scanptr.p->scanReleaseCounter -1,
false);
signal->theData[2] = NextScanReq::ZSCAN_COMMIT;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
}//Dblqh::continueScanReleaseAfterBlockedLab()
/* -------------------------------------------------------------------------
@@ -7280,7 +7270,6 @@ void Dblqh::closeScanRequestLab(Signal* signal)
jam();
tupScanCloseConfLab(signal);
break;
- case ScanRecord::WAIT_SCAN_KEYINFO:
case ScanRecord::WAIT_NEXT_SCAN:
jam();
/* -------------------------------------------------------------------
@@ -7344,6 +7333,7 @@ void Dblqh::closeScanRequestLab(Signal* signal)
* WE ARE STILL WAITING FOR THE ATTRIBUTE INFORMATION THAT
* OBVIOUSLY WILL NOT ARRIVE. WE CAN QUIT IMMEDIATELY HERE.
* --------------------------------------------------------------------- */
+ //XXX jonas this have to be wrong...
releaseOprec(signal);
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
jam();
@@ -7410,15 +7400,15 @@ void Dblqh::scanLockReleasedLab(Signal* signal)
scanptr.p->m_curr_batch_size_rows = 0;
scanptr.p->m_curr_batch_size_bytes = 0;
closeScanLab(signal);
+ } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) {
+ jam();
+ closeScanLab(signal);
+ return;
} else if (scanptr.p->check_scan_batch_completed() &&
scanptr.p->scanLockHold != ZTRUE) {
jam();
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
sendScanFragConf(signal, ZFALSE);
- } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) {
- jam();
- closeScanLab(signal);
- return;
} else {
jam();
/*
@@ -7565,6 +7555,7 @@ void Dblqh::execSCAN_FRAGREQ(Signal* signal)
const Uint32 scanLockMode = ScanFragReq::getLockMode(reqinfo);
const Uint8 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
const Uint8 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
+ const Uint8 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
if(tabptr.p->tableStatus != Tablerec::TABLE_DEFINED){
@@ -7709,18 +7700,13 @@ void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
req->fragmentNo = tcConnectptr.p->fragmentid;
req->requestInfo = 0;
AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
- AccScanReq::setKeyinfoFlag(req->requestInfo, scanptr.p->scanKeyinfoFlag);
AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
+ AccScanReq::setDescendingFlag(req->requestInfo, scanptr.p->descending);
req->transId1 = tcConnectptr.p->transid[0];
req->transId2 = tcConnectptr.p->transid[1];
req->savePointId = tcConnectptr.p->savePointId;
- // always use if-stmt to switch (instead of setting a "scan block ref")
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_ACC_SCANREQ, signal,
- AccScanReq::SignalLength, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_ACC_SCANREQ, signal,
- AccScanReq::SignalLength, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_ACC_SCANREQ, signal,
+ AccScanReq::SignalLength, JBB);
}//Dblqh::continueAfterReceivingAllAiLab()
void Dblqh::scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
@@ -7814,11 +7800,6 @@ void Dblqh::execSCAN_HBREP(Signal* signal)
}
}
-void Dblqh::sendScanFragRefLateLab(Signal* signal)
-{
-}//Dblqh::sendScanFragRefLateLab()
-
-
void Dblqh::accScanConfScanLab(Signal* signal)
{
AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
@@ -7837,17 +7818,15 @@ void Dblqh::accScanConfScanLab(Signal* signal)
return;
}//if
scanptr.p->scanAccPtr = accScanConf->accPtr;
- Uint32 boundAiLength = tcConnectptr.p->primKeyLen - 4;
if (scanptr.p->rangeScan) {
jam();
- TuxBoundInfo* const req = (TuxBoundInfo*)signal->getDataPtrSend();
+ TuxBoundInfo* req = (TuxBoundInfo*)signal->getDataPtrSend();
req->errorCode = RNIL;
req->tuxScanPtrI = scanptr.p->scanAccPtr;
- req->boundAiLength = boundAiLength;
- if(boundAiLength > 0)
- sendKeyinfoAcc(signal, TuxBoundInfo::SignalLength);
- EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO,
- signal, TuxBoundInfo::SignalLength + boundAiLength);
+ Uint32 len = req->boundAiLength = copy_bounds(req->data, tcConnectptr.p);
+ EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO, signal,
+ TuxBoundInfo::SignalLength + len);
+
jamEntry();
if (req->errorCode != 0) {
jam();
@@ -7859,35 +7838,176 @@ void Dblqh::accScanConfScanLab(Signal* signal)
tcConnectptr.p->errorCode = req->errorCode;
}
}
- scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- signal->theData[1] = tcConnectptr.p->tableref;
- signal->theData[2] = scanptr.p->scanSchemaVersion;
- signal->theData[3] = ZSTORED_PROC_SCAN;
- signal->theData[4] = scanptr.p->scanAiLength;
- sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_STORED_PROCREQ, signal, 5, JBB);
-
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
- while (regAttrinbufptr.i != RNIL) {
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
+ if(scanptr.p->scanStoredProcId == RNIL)
+ {
jam();
- Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
- ndbrequire(dataLen != 0);
- // first 3 words already set in STORED_PROCREQ
- MEMCOPY_NO_WORDS(&signal->theData[3],
- &regAttrinbufptr.p->attrbuf[0],
- dataLen);
+ signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ signal->theData[1] = tcConnectptr.p->tableref;
+ signal->theData[2] = scanptr.p->scanSchemaVersion;
+ signal->theData[3] = ZSTORED_PROC_SCAN;
+
+ signal->theData[4] = scanptr.p->scanAiLength;
sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_ATTRINFO, signal, dataLen + 3, JBB);
- regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
- }//while
- releaseOprec(signal);
+ GSN_STORED_PROCREQ, signal, 5, JBB);
+
+ signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ AttrbufPtr regAttrinbufptr;
+ Uint32 firstAttr = regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
+ while (regAttrinbufptr.i != RNIL) {
+ ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ jam();
+ Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
+ ndbrequire(dataLen != 0);
+ // first 3 words already set in STORED_PROCREQ
+ MEMCOPY_NO_WORDS(&signal->theData[3],
+ &regAttrinbufptr.p->attrbuf[0],
+ dataLen);
+ sendSignal(tcConnectptr.p->tcTupBlockref,
+ GSN_ATTRINFO, signal, dataLen + 3, JBB);
+ regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
+ c_no_attrinbuf_recs++;
+ }//while
+
+ /**
+ * Release attr info
+ */
+ if(firstAttr != RNIL)
+ {
+ regAttrinbufptr.p->attrbuf[ZINBUF_NEXT] = cfirstfreeAttrinbuf;
+ cfirstfreeAttrinbuf = firstAttr;
+ tcConnectptr.p->firstAttrinbuf = tcConnectptr.p->lastAttrinbuf = RNIL;
+ }
+ }
+ else
+ {
+ jam();
+ storedProcConfScanLab(signal);
+ }
}//Dblqh::accScanConfScanLab()
+#define print_buf(s,idx,len) {\
+ printf(s); Uint32 t2=len; DatabufPtr t3; t3.i = idx; \
+ while(t3.i != RNIL && t2-- > 0){\
+ ptrCheckGuard(t3, cdatabufFileSize, databuf);\
+ printf("%d ", t3.i); t3.i= t3.p->nextDatabuf;\
+ } printf("\n"); }
+
+Uint32
+Dblqh::copy_bounds(Uint32 * dst, TcConnectionrec* tcPtrP)
+{
+ /**
+ * copy_bounds handles multiple bounds by
+ * in the 16 upper bits of the first words (used to specify bound type)
+ * setting the length of this specific bound
+ *
+ */
+
+ DatabufPtr regDatabufptr;
+ Uint32 left = 4 - tcPtrP->m_offset_current_keybuf; // left in buf
+ Uint32 totalLen = tcPtrP->primKeyLen - 4;
+ regDatabufptr.i = tcPtrP->firstTupkeybuf;
+
+ ndbassert(tcPtrP->primKeyLen >= 4);
+ ndbassert(tcPtrP->m_offset_current_keybuf < 4);
+ ndbassert(!(totalLen == 0 && regDatabufptr.i != RNIL));
+ ndbassert(!(totalLen != 0 && regDatabufptr.i == RNIL));
+
+ if(totalLen)
+ {
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ Uint32 sig0 = regDatabufptr.p->data[0];
+ Uint32 sig1 = regDatabufptr.p->data[1];
+ Uint32 sig2 = regDatabufptr.p->data[2];
+ Uint32 sig3 = regDatabufptr.p->data[3];
+
+ switch(left){
+ case 4:
+ * dst++ = sig0;
+ case 3:
+ * dst++ = sig1;
+ case 2:
+ * dst++ = sig2;
+ case 1:
+ * dst++ = sig3;
+ }
+
+ Uint32 first = (* (dst - left)); // First word in range
+
+ // Length of this range
+ Uint8 offset;
+ const Uint32 len = (first >> 16) ? (first >> 16) : totalLen;
+ tcPtrP->m_scan_curr_range_no = (first & 0xFFF0) >> 4;
+ (* (dst - left)) = (first & 0xF); // Remove length & range no
+
+ if(len < left)
+ {
+ offset = len;
+ }
+ else
+ {
+ Databuf * lastP;
+ left = (len - left);
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+
+ while(left >= 4)
+ {
+ left -= 4;
+ lastP = regDatabufptr.p;
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ sig0 = regDatabufptr.p->data[0];
+ sig1 = regDatabufptr.p->data[1];
+ sig2 = regDatabufptr.p->data[2];
+ sig3 = regDatabufptr.p->data[3];
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+
+ * dst++ = sig0;
+ * dst++ = sig1;
+ * dst++ = sig2;
+ * dst++ = sig3;
+ }
+
+ if(left > 0)
+ {
+ lastP = regDatabufptr.p;
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ sig0 = regDatabufptr.p->data[0];
+ sig1 = regDatabufptr.p->data[1];
+ sig2 = regDatabufptr.p->data[2];
+ sig3 = regDatabufptr.p->data[3];
+ * dst++ = sig0;
+ * dst++ = sig1;
+ * dst++ = sig2;
+ * dst++ = sig3;
+ }
+ else
+ {
+ lastP = regDatabufptr.p;
+ }
+ offset = left & 3;
+ lastP->nextDatabuf = cfirstfreeDatabuf;
+ cfirstfreeDatabuf = tcPtrP->firstTupkeybuf;
+ ndbassert(cfirstfreeDatabuf != RNIL);
+ }
+
+ if(len == totalLen && regDatabufptr.i != RNIL)
+ {
+ regDatabufptr.p->nextDatabuf = cfirstfreeDatabuf;
+ cfirstfreeDatabuf = regDatabufptr.i;
+ tcPtrP->lastTupkeybuf = regDatabufptr.i = RNIL;
+ ndbassert(cfirstfreeDatabuf != RNIL);
+ }
+
+ tcPtrP->m_offset_current_keybuf = offset;
+ tcPtrP->firstTupkeybuf = regDatabufptr.i;
+ tcPtrP->primKeyLen = 4 + totalLen - len;
+
+ return len;
+ }
+ return totalLen;
+}
+
/* -------------------------------------------------------------------------
* ENTER STORED_PROCCONF WITH
* TC_CONNECTPTR,
@@ -7938,14 +8058,10 @@ void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
- init_acc_ptr_list(scanptr.p);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_NEXT;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
return;
}//Dblqh::continueFirstScanAfterBlockedLab()
@@ -8015,10 +8131,8 @@ void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
c_scanRecordPool.getPtr(scanptr);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
- if (! scanptr.p->rangeScan)
- EXECUTE_DIRECT(DBACC, GSN_ACC_CHECK_SCAN, signal, 2);
- else
- EXECUTE_DIRECT(DBTUX, GSN_ACC_CHECK_SCAN, signal, 2);
+ EXECUTE_DIRECT(refToBlock(scanptr.p->scanBlockref), GSN_ACC_CHECK_SCAN,
+ signal, 2);
}//Dblqh::continueAfterCheckLcpStopBlocked()
/* -------------------------------------------------------------------------
@@ -8066,7 +8180,10 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
if (scanptr.p->m_curr_batch_size_rows > 0) {
jam();
- scanptr.p->scanCompletedStatus = ZTRUE;
+
+ if((tcConnectptr.p->primKeyLen - 4) == 0)
+ scanptr.p->scanCompletedStatus = ZTRUE;
+
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
sendScanFragConf(signal, ZFALSE);
return;
@@ -8105,12 +8222,8 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref,
- GSN_ACC_CHECK_SCAN, signal, 2, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref,
- GSN_ACC_CHECK_SCAN, signal, 2, JBB);
+ sendSignal(scanptr.p->scanBlockref,
+ GSN_ACC_CHECK_SCAN, signal, 2, JBB);
return;
}//if
jam();
@@ -8121,22 +8234,6 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
scanptr.p->scanLocalFragid = nextScanConf->fragId;
- if (scanptr.p->scanKeyinfoFlag) {
- jam();
- tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
- seizeTupkeybuf(signal);
- databufptr.p->data[0] = nextScanConf->key[0];
- databufptr.p->data[1] = nextScanConf->key[1];
- databufptr.p->data[2] = nextScanConf->key[2];
- databufptr.p->data[3] = nextScanConf->key[3];
- if (nextScanConf->keyLength > 4) {
- jam();
- tcConnectptr.p->save1 = 4;
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_KEYINFO;
- return;
- }//if
- }//if
- jam();
nextScanConfLoopLab(signal);
}//Dblqh::nextScanConfScanLab()
@@ -8148,7 +8245,6 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
if (scanptr.p->scanCompletedStatus == ZTRUE) {
jam();
releaseActiveFrag(signal);
- releaseOprec(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8170,13 +8266,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
if (! scanptr.p->rangeScan) {
tableRef = tcConnectptr.p->tableref;
- if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[1];
- }//if
+ tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
} else {
jam();
// for ordered index use primary table
@@ -8184,13 +8274,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
tFragPtr.i = fragptr.p->tableFragptr;
ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
tableRef = tFragPtr.p->tabRef;
- if (tFragPtr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = tFragPtr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = tFragPtr.p->tupFragptr[1];
- }//if
+ tupFragPtr = tFragPtr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
}
{
jam();
@@ -8225,33 +8309,46 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
* -------------------------------------------------------------------------
* PRECONDITION: SCAN_STATE = WAIT_SCAN_KEYINFO
* ------------------------------------------------------------------------- */
-bool Dblqh::keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
+void
+Dblqh::keyinfoLab(const Uint32 * src, const Uint32 * end)
{
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- Uint32 index = 0;
do {
jam();
- seizeTupkeybuf(signal);
- databufptr.p->data[0] = dataPtr[index];
- databufptr.p->data[1] = dataPtr[index + 1];
- databufptr.p->data[2] = dataPtr[index + 2];
- databufptr.p->data[3] = dataPtr[index + 3];
- index += 4;
- tcConnectptr.p->save1 = tcConnectptr.p->save1 + 4;
- if (tcConnectptr.p->save1 >= tcConnectptr.p->primKeyLen) {
- jam();
- return true;
- }//if
- if (index >= length) {
- jam();
- return false;
- }//if
- } while (index < 20);
- ndbrequire(false);
- return false;
+ seizeTupkeybuf(0);
+ databufptr.p->data[0] = * src ++;
+ databufptr.p->data[1] = * src ++;
+ databufptr.p->data[2] = * src ++;
+ databufptr.p->data[3] = * src ++;
+ } while (src < end);
}//Dblqh::keyinfoLab()
+Uint32
+Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
+{
+ Uint32 tableId = tcConP->tableref;
+ Uint32 fragId = scanP->scanLocalFragid;
+ Uint32 fragPageId = scanP->scanLocalref[0];
+ Uint32 pageIndex = scanP->scanLocalref[1];
+
+ if(scanP->rangeScan)
+ {
+ jam();
+ // for ordered index use primary table
+ FragrecordPtr tFragPtr;
+ tFragPtr.i = fragptr.p->tableFragptr;
+ ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ tableId = tFragPtr.p->tabRef;
+ }
+
+ int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst, false);
+ if(0)
+ ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
+ tableId, fragId, fragPageId, pageIndex, ret);
+ ndbassert(ret > 0);
+
+ return ret;
+}
+
/* -------------------------------------------------------------------------
* ENTER TUPKEYCONF
* -------------------------------------------------------------------------
@@ -8271,7 +8368,6 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
/* ---------------------------------------------------------------------
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
* --------------------------------------------------------------------- */
- releaseOprec(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8285,10 +8381,8 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
}//if
if (scanptr.p->scanKeyinfoFlag) {
jam();
- sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
- releaseOprec(signal);
-
- tdata4 += tcConnectptr.p->primKeyLen;// Inform API about keyinfo len aswell
+ // Inform API about keyinfo len aswell
+ tdata4 += sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
}//if
ndbrequire(scanptr.p->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
scanptr.p->m_curr_batch_size_bytes+= tdata4;
@@ -8372,10 +8466,7 @@ void Dblqh::continueScanAfterBlockedLab(Signal* signal)
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = accOpPtr;
signal->theData[2] = scanptr.p->scanFlag;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3,JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3,JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
}//Dblqh::continueScanAfterBlockedLab()
/* -------------------------------------------------------------------------
@@ -8390,7 +8481,6 @@ void Dblqh::scanTupkeyRefLab(Signal* signal)
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
scanptr.i = tcConnectptr.p->tcScanRec;
releaseActiveFrag(signal);
- releaseOprec(signal);
c_scanRecordPool.getPtr(scanptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
/* ---------------------------------------------------------------------
@@ -8498,10 +8588,7 @@ void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_CLOSE;
- if (! scanptr.p->rangeScan)
- sendSignal(tcConnectptr.p->tcAccBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
- else
- sendSignal(tcConnectptr.p->tcTuxBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
+ sendSignal(scanptr.p->scanBlockref, GSN_NEXT_SCANREQ, signal, 3, JBB);
}//Dblqh::continueCloseScanAfterBlockedLab()
/* -------------------------------------------------------------------------
@@ -8512,8 +8599,18 @@ void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
void Dblqh::accScanCloseConfLab(Signal* signal)
{
tcConnectptr.i = scanptr.p->scanTcrec;
- scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+
+ if((tcConnectptr.p->primKeyLen - 4) > 0 &&
+ scanptr.p->scanCompletedStatus != ZTRUE)
+ {
+ jam();
+ releaseActiveFrag(signal);
+ continueAfterReceivingAllAiLab(signal);
+ return;
+ }
+
+ scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
signal->theData[0] = tcConnectptr.p->tupConnectrec;
signal->theData[1] = tcConnectptr.p->tableref;
signal->theData[2] = scanptr.p->scanSchemaVersion;
@@ -8575,7 +8672,9 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
- const Uint32 idx = ScanFragReq::getRangeScanFlag(reqinfo);
+ const Uint32 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
+ const Uint32 descending = ScanFragReq::getDescendingFlag(reqinfo);
+ const Uint32 tupScan = ScanFragReq::getTupScanFlag(reqinfo);
const Uint32 attrLen = ScanFragReq::getAttrLen(reqinfo);
const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
@@ -8593,10 +8692,19 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->m_max_batch_size_rows = max_rows;
scanptr.p->m_max_batch_size_bytes = max_bytes;
+ if (! rangeScan && ! tupScan)
+ scanptr.p->scanBlockref = tcConnectptr.p->tcAccBlockref;
+ else if (! tupScan)
+ scanptr.p->scanBlockref = tcConnectptr.p->tcTuxBlockref;
+ else
+ scanptr.p->scanBlockref = tcConnectptr.p->tcTupBlockref;
+
scanptr.p->scanErrorCounter = 0;
scanptr.p->scanLockMode = scanLockMode;
scanptr.p->readCommitted = readCommitted;
- scanptr.p->rangeScan = idx;
+ scanptr.p->rangeScan = rangeScan;
+ scanptr.p->descending = descending;
+ scanptr.p->tupScan = tupScan;
scanptr.p->scanState = ScanRecord::SCAN_FREE;
scanptr.p->scanFlag = ZFALSE;
scanptr.p->scanLocalref[0] = 0;
@@ -8606,6 +8714,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->scanNumber = ~0;
scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
scanptr.p->m_last_row = 0;
+ scanptr.p->scanStoredProcId = RNIL;
if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
jam();
@@ -8627,8 +8736,8 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
* !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1) = 1-11
* idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
*/
- Uint32 start = (idx ? MAX_PARALLEL_SCANS_PER_FRAG : 1 );
- Uint32 stop = (idx ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
+ Uint32 start = (rangeScan || tupScan ? MAX_PARALLEL_SCANS_PER_FRAG : 1 );
+ Uint32 stop = (rangeScan || tupScan ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
stop += start;
Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
@@ -8664,7 +8773,8 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
#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);
+ tabptr.i, scanFragReq->fragmentNoKeyLen & 0xFFFF,
+ fragptr.i, fragptr.p->tableFragptr);
#endif
c_scanTakeOverHash.add(scanptr);
}
@@ -8700,6 +8810,8 @@ void Dblqh::initScanTc(Signal* signal,
tcConnectptr.p->operation = ZREAD;
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
tcConnectptr.p->commitAckMarker = RNIL;
+ tcConnectptr.p->m_offset_current_keybuf = 0;
+ tcConnectptr.p->m_scan_curr_range_no = 0;
tabptr.p->usageCount++;
}//Dblqh::initScanTc()
@@ -8814,23 +8926,17 @@ void Dblqh::releaseScanrec(Signal* signal)
* ------- SEND KEYINFO20 TO API -------
*
* ------------------------------------------------------------------------ */
-void Dblqh::sendKeyinfo20(Signal* signal,
- ScanRecord * scanP,
- TcConnectionrec * tcConP)
+Uint32 Dblqh::sendKeyinfo20(Signal* signal,
+ ScanRecord * scanP,
+ TcConnectionrec * tcConP)
{
ndbrequire(scanP->m_curr_batch_size_rows < 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->m_curr_batch_size_rows;
const Uint32 nodeId = refToNode(ref);
@@ -8843,24 +8949,12 @@ void Dblqh::sendKeyinfo20(Signal* signal,
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;
- }
-
+ Uint32 keyLen = readPrimaryKeys(scanP, tcConP, dst);
+ Uint32 fragId = tcConP->fragmentid;
keyInfo->clientOpPtr = scanP->scanApiOpPtr;
keyInfo->keyLen = keyLen;
- keyInfo->scanInfo_Node = KeyInfo20::setScanInfo(scanOp,
- scanP->scanNumber)+
- (getOwnNodeId() << 20);
+ keyInfo->scanInfo_Node =
+ KeyInfo20::setScanInfo(scanOp, scanP->scanNumber) + (fragId << 20);
keyInfo->transId1 = tcConP->transid[0];
keyInfo->transId2 = tcConP->transid[1];
@@ -8883,7 +8977,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
sendSignal(ref, GSN_KEYINFO20, signal,
KeyInfo20::HeaderLength+keyLen, JBB);
- return;
+ return keyLen;
}
LinearSectionPtr ptr[3];
@@ -8891,13 +8985,13 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ptr[0].sz = keyLen;
sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
JBB, ptr, 1);
- return;
+ return keyLen;
}
EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
KeyInfo20::HeaderLength + keyLen);
jamEntry();
- return;
+ return keyLen;
}
/**
@@ -8923,7 +9017,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
keyInfo->keyData[keyLen] = ref;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
KeyInfo20::HeaderLength+keyLen+1, JBB);
- return;
+ return keyLen;
}
keyInfo->keyData[0] = ref;
@@ -8932,7 +9026,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ptr[0].sz = keyLen;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
KeyInfo20::HeaderLength+1, JBB, ptr, 1);
- return;
+ return keyLen;
}
/* ------------------------------------------------------------------------
@@ -8981,44 +9075,17 @@ void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
/* FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL */
/* CONNECTIONS TO THE FAILED NODE. */
/*---------------------------------------------------------------------------*/
-void Dblqh::calculateHash(Signal* signal)
-{
- DatabufPtr locDatabufptr;
- UintR Ti;
- UintR Tdata0;
- UintR Tdata1;
- UintR Tdata2;
- UintR Tdata3;
- UintR* Tdata32;
- Uint64 Tdata[512];
-
- Tdata32 = (UintR*)&Tdata[0];
-
- Tdata0 = tcConnectptr.p->tupkeyData[0];
- Tdata1 = tcConnectptr.p->tupkeyData[1];
- Tdata2 = tcConnectptr.p->tupkeyData[2];
- Tdata3 = tcConnectptr.p->tupkeyData[3];
- Tdata32[0] = Tdata0;
- Tdata32[1] = Tdata1;
- Tdata32[2] = Tdata2;
- Tdata32[3] = Tdata3;
- locDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
- Ti = 4;
- while (locDatabufptr.i != RNIL) {
- ptrCheckGuard(locDatabufptr, cdatabufFileSize, databuf);
- Tdata0 = locDatabufptr.p->data[0];
- Tdata1 = locDatabufptr.p->data[1];
- Tdata2 = locDatabufptr.p->data[2];
- Tdata3 = locDatabufptr.p->data[3];
- Tdata32[Ti ] = Tdata0;
- Tdata32[Ti + 1] = Tdata1;
- Tdata32[Ti + 2] = Tdata2;
- Tdata32[Ti + 3] = Tdata3;
- locDatabufptr.i = locDatabufptr.p->nextDatabuf;
- Ti += 4;
- }//while
- tcConnectptr.p->hashValue =
- md5_hash((Uint64*)&Tdata32[0], (UintR)tcConnectptr.p->primKeyLen);
+Uint32
+Dblqh::calculateHash(Uint32 tableId, const Uint32* src)
+{
+ jam();
+ Uint64 Tmp[(MAX_KEY_SIZE_IN_WORDS*MAX_XFRM_MULTIPLY) >> 1];
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32 keyLen = xfrm_key(tableId, src, (Uint32*)Tmp, sizeof(Tmp) >> 2,
+ keyPartLen);
+ ndbrequire(keyLen);
+
+ return md5_hash(Tmp, keyLen);
}//Dblqh::calculateHash()
/* *************************************** */
@@ -9070,6 +9137,7 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
/* ------------------------------------------------------------------------- */
scanptr.p->m_max_batch_size_rows = 0;
scanptr.p->rangeScan = 0;
+ scanptr.p->tupScan = 0;
seizeTcrec();
/**
@@ -9088,6 +9156,7 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
scanptr.p->fragPtrI = fragptr.i;
fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
+ scanptr.p->scanBlockref = DBACC_REF;
initScanTc(signal,
0,
@@ -9108,7 +9177,6 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
req->fragmentNo = fragId;
req->requestInfo = 0;
AccScanReq::setLockMode(req->requestInfo, 0);
- AccScanReq::setKeyinfoFlag(req->requestInfo, 1);
AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
req->transId1 = tcConnectptr.p->transid[0];
req->transId2 = tcConnectptr.p->transid[1];
@@ -9192,7 +9260,7 @@ void Dblqh::storedProcConfCopyLab(Signal* signal)
jam();
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -9270,12 +9338,6 @@ void Dblqh::nextScanConfCopyLab(Signal* signal)
set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
initCopyTc(signal);
- if (tcConnectptr.p->primKeyLen > 4) {
- jam();
- tcConnectptr.p->save1 = 4;
- scanptr.p->scanState = ScanRecord::WAIT_COPY_KEYINFO;
- return;
- }//if
copySendTupkeyReqLab(signal);
return;
}//Dblqh::nextScanConfCopyLab()
@@ -9291,13 +9353,7 @@ void Dblqh::copySendTupkeyReqLab(Signal* signal)
scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
fragptr.i = tcConnectptr.p->fragmentptr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[1];
- }//if
+ tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
{
TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
@@ -9372,9 +9428,10 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
UintR readLength = tupKeyConf->readLength;
-
+ Uint32 tableId = tcConnectptr.p->tableref;
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
+ ScanRecord* scanP = scanptr.p;
releaseActiveFrag(signal);
if (tcConnectptr.p->errorCode != 0) {
jam();
@@ -9389,9 +9446,30 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
closeCopyLab(signal);
return;
}//if
+ TcConnectionrec * tcConP = tcConnectptr.p;
tcConnectptr.p->totSendlenAi = readLength;
tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
- calculateHash(signal);
+
+ // Read primary keys (used to get here via scan keyinfo)
+ Uint32* tmp = signal->getDataPtrSend()+24;
+ Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
+
+ // Calculate hash (no need to linearies key)
+ if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
+ {
+ tcConnectptr.p->hashValue = calculateHash(tableId, tmp);
+ }
+ else
+ {
+ tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
+ }
+
+ // Move into databuffer to make packLqhkeyreqLab happy
+ memcpy(tcConP->tupkeyData, tmp, 4*4);
+ if(len > 4)
+ keyinfoLab(tmp+4, tmp + len);
+ LqhKeyReq::setKeyLen(tcConP->reqinfo, len);
+
/*---------------------------------------------------------------------------*/
// To avoid using up to many operation records in ACC we will increase the
// constant to ensure that we never send more than 40 records at a time.
@@ -9402,7 +9480,7 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
// records to ensure that node recovery does not fail because of simultaneous
// scanning.
/*---------------------------------------------------------------------------*/
- UintR TnoOfWords = readLength + tcConnectptr.p->primKeyLen;
+ UintR TnoOfWords = readLength + len;
TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
@@ -9483,7 +9561,7 @@ void Dblqh::copyCompletedLab(Signal* signal)
// Make sure that something is in progress. Otherwise we will simply stop
// and nothing more will happen.
/*---------------------------------------------------------------------------*/
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
return;
@@ -9502,7 +9580,7 @@ void Dblqh::nextRecordCopy(Signal* signal)
// scans on the same record and this will certainly lead to unexpected
// behaviour.
/*---------------------------------------------------------------------------*/
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
@@ -9529,7 +9607,7 @@ void Dblqh::nextRecordCopy(Signal* signal)
jam();
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -9603,7 +9681,7 @@ void Dblqh::closeCopyLab(Signal* signal)
jam();
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -9724,7 +9802,6 @@ void Dblqh::closeCopyRequestLab(Signal* signal)
scanptr.p->scanErrorCounter++;
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_TUPKEY_COPY:
- case ScanRecord::WAIT_COPY_KEYINFO:
case ScanRecord::WAIT_NEXT_SCAN_COPY:
jam();
/*---------------------------------------------------------------------------*/
@@ -9955,11 +10032,6 @@ void Dblqh::execCOPY_STATEREQ(Signal* signal)
void Dblqh::initCopyTc(Signal* signal)
{
const NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
- tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
- tcConnectptr.p->tupkeyData[0] = nextScanConf->key[0];
- tcConnectptr.p->tupkeyData[1] = nextScanConf->key[1];
- tcConnectptr.p->tupkeyData[2] = nextScanConf->key[2];
- tcConnectptr.p->tupkeyData[3] = nextScanConf->key[3];
scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
scanptr.p->scanLocalFragid = nextScanConf->fragId;
@@ -9968,7 +10040,6 @@ void Dblqh::initCopyTc(Signal* signal)
tcConnectptr.p->opExec = 0; /* NOT INTERPRETED MODE */
tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
Uint32 reqinfo = 0;
- LqhKeyReq::setKeyLen(reqinfo, nextScanConf->keyLength);
LqhKeyReq::setLockType(reqinfo, ZINSERT);
LqhKeyReq::setDirtyFlag(reqinfo, 1);
LqhKeyReq::setSimpleFlag(reqinfo, 1);
@@ -10631,7 +10702,7 @@ void Dblqh::restartOperationsAfterStopLab(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -11455,7 +11526,7 @@ void Dblqh::execGCP_SAVEREQ(Signal* signal)
const GCPSaveReq * const saveReq = (GCPSaveReq *)&signal->theData[0];
if (ERROR_INSERTED(5000)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}
if (ERROR_INSERTED(5007)){
@@ -11821,7 +11892,7 @@ void Dblqh::execFSCLOSECONF(Signal* signal)
return;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//Dblqh::execFSCLOSECONF()
@@ -11896,7 +11967,7 @@ void Dblqh::execFSOPENCONF(Signal* signal)
return;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//Dblqh::execFSOPENCONF()
@@ -11955,7 +12026,7 @@ void Dblqh::execFSREADCONF(Signal* signal)
return;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//Dblqh::execFSREADCONF()
@@ -12057,7 +12128,7 @@ void Dblqh::execFSWRITECONF(Signal* signal)
return;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//Dblqh::execFSWRITECONF()
@@ -12101,7 +12172,7 @@ void Dblqh::execFSWRITEREF(Signal* signal)
break;
case LogFileOperationRecord::WRITE_SR_INVALIDATE_PAGES:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
default:
jam();
break;
@@ -12315,7 +12386,7 @@ void Dblqh::writeLogfileLab(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -13485,7 +13556,6 @@ void Dblqh::execSR_FRAGIDCONF(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
fragptr.p->accFragptr[0] = srFragidConf->fragPtr[0];
fragptr.p->accFragptr[1] = srFragidConf->fragPtr[1];
- fragptr.p->hashCheckBit = srFragidConf->hashCheckBit;
Uint32 noLocFrag = srFragidConf->noLocFrag;
ndbrequire(noLocFrag == 2);
Uint32 fragid[2];
@@ -13548,7 +13618,7 @@ void Dblqh::execACC_SRCONF(Signal* signal)
ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
if (lcpLocptr.p->lcpLocstate != LcpLocRecord::SR_ACC_STARTED) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
@@ -13570,7 +13640,7 @@ void Dblqh::execACC_SRREF(Signal* signal)
{
jamEntry();
terrorCode = signal->theData[1];
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dblqh::execACC_SRREF()
@@ -13710,7 +13780,7 @@ void Dblqh::execTUP_SRREF(Signal* signal)
{
jamEntry();
terrorCode = signal->theData[1];
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dblqh::execTUP_SRREF()
@@ -14010,7 +14080,7 @@ void Dblqh::execEXEC_FRAGREF(Signal* signal)
{
jamEntry();
terrorCode = signal->theData[1];
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dblqh::execEXEC_FRAGREF()
@@ -14102,7 +14172,7 @@ void Dblqh::execSrCompletedLab(Signal* signal)
* PROBLEM. THIS SHOULD NOT OCCUR. IF IT OCCURS ANYWAY THEN WE
* HAVE TO FIND A CURE FOR THIS PROBLEM.
* ----------------------------------------------------------------- */
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
signal->theData[0] = ZSR_LOG_LIMITS;
@@ -14629,7 +14699,7 @@ void Dblqh::execSr(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -14912,7 +14982,7 @@ void Dblqh::execDEBUG_SIG(Signal* signal)
signal->theData[2], signal->theData[3], signal->theData[4],
signal->theData[5], signal->theData[6], signal->theData[7]);
- progError(__LINE__, ERR_SR_REDOLOG, buf);
+ progError(__LINE__, NDBD_EXIT_SR_REDOLOG, buf);
return;
}//Dblqh::execDEBUG_SIG()
@@ -14984,12 +15054,12 @@ void Dblqh::invalidateLogAfterLastGCI(Signal* signal) {
jam();
if (logPartPtr.p->logExecState != LogPartRecord::LES_EXEC_LOG_INVALIDATE) {
jam();
- systemError(signal);
+ systemError(signal, __LINE__);
}
if (logFilePtr.p->fileNo != logPartPtr.p->invalidateFileNo) {
jam();
- systemError(signal);
+ systemError(signal, __LINE__);
}
switch (lfoPtr.p->lfoState) {
@@ -15044,7 +15114,7 @@ void Dblqh::invalidateLogAfterLastGCI(Signal* signal) {
default:
jam();
- systemError(signal);
+ systemError(signal, __LINE__);
return;
break;
}
@@ -15192,7 +15262,7 @@ void Dblqh::execLogComp(Signal* signal)
if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_COMPLETED) {
if (logPartPtr.p->logPartState != LogPartRecord::SR_THIRD_PHASE_STARTED) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
} else {
jam();
@@ -15450,7 +15520,7 @@ void Dblqh::openSrFourthZeroSkipInitLab(Signal* signal)
* THE HEADER PAGE IN THE LOG IS PAGE ZERO IN FILE ZERO.
* THIS SHOULD NEVER OCCUR.
* ------------------------------------------------------------------- */
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
}//if
@@ -15508,7 +15578,7 @@ void Dblqh::srFourthComp(Signal* signal)
if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_COMPLETED) {
if (logPartPtr.p->logPartState != LogPartRecord::SR_FOURTH_PHASE_STARTED) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
} else {
jam();
@@ -15570,11 +15640,6 @@ void Dblqh::srFourthComp(Signal* signal)
/* ####### ERROR MODULE ####### */
/* */
/* ######################################################################### */
-void Dblqh::warningHandlerLab(Signal* signal)
-{
- systemErrorLab(signal);
- return;
-}//Dblqh::warningHandlerLab()
/*---------------------------------------------------------------------------*/
/* AN ERROR OCCURRED THAT WE WILL NOT TREAT AS SYSTEM ERROR. MOST OFTEN THIS */
@@ -15595,9 +15660,10 @@ void Dblqh::warningHandlerLab(Signal* signal)
/* THE COMMIT, COMPLETE OR ABORT PHASE, WE PERFORM A CRASH OF THE AXE VM*/
/*---------------------------------------------------------------------------*/
-void Dblqh::systemErrorLab(Signal* signal)
+void Dblqh::systemErrorLab(Signal* signal, int line)
{
- progError(0, 0);
+ systemError(signal, line);
+ progError(line, NDBD_EXIT_NDBREQUIRE);
/*************************************************************************>*/
/* WE WANT TO INVOKE AN IMMEDIATE ERROR HERE SO WE GET THAT BY */
/* INSERTING A CERTAIN POINTER OUT OF RANGE. */
@@ -15806,7 +15872,7 @@ void Dblqh::buildLinkedLogPageList(Signal* signal)
// Uint32 checkSum = bllLogPagePtr.p->logPageWord[ZPOS_CHECKSUM];
// if (checkSum != calcCheckSum) {
// ndbout << "Redolog: Checksum failure." << endl;
-// progError(__LINE__, ERR_NDBREQUIRE, "Redolog: Checksum failure.");
+// progError(__LINE__, NDBD_EXIT_NDBREQUIRE, "Redolog: Checksum failure.");
// }
// #endif
@@ -15932,7 +15998,7 @@ CSC_ACC_DOWHILE:
jam();
if (cscLcpLocptr.p->lcpLocstate != LcpLocRecord::SR_ACC_STARTED) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
return;
@@ -15949,7 +16015,7 @@ CSC_TUP_DOWHILE:
jam();
if (cscLcpLocptr.p->lcpLocstate != LcpLocRecord::SR_TUP_STARTED) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
return;
@@ -16160,7 +16226,7 @@ error:
"Unable to restart, failed while reading redo."
" Likely invalid change of configuration");
progError(__LINE__,
- ERR_INVALID_CONFIG,
+ NDBD_EXIT_INVALID_CONFIG,
buf);
}//Dblqh::findLogfile()
@@ -17531,7 +17597,7 @@ void Dblqh::releaseAccList(Signal* signal)
racTcNextConnectptr.i = tcConnectptr.p->nextTc;
if (tcConnectptr.p->listState != TcConnectionrec::ACC_BLOCK_LIST) {
jam();
- systemError(signal);
+ systemError(signal, __LINE__);
}//if
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
if (racTcNextConnectptr.i != RNIL) {
@@ -17710,7 +17776,7 @@ void Dblqh::releaseWaitQueue(Signal* signal)
rwaTcNextConnectptr.i = tcConnectptr.p->nextTc;
if (tcConnectptr.p->listState != TcConnectionrec::WAIT_QUEUE_LIST) {
jam();
- systemError(signal);
+ systemError(signal, __LINE__);
}//if
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
if (rwaTcNextConnectptr.i != RNIL) {
@@ -17973,7 +18039,8 @@ void Dblqh::stepAhead(Signal* signal, Uint32 stepAheadWords)
logFilePtr.p->currentLogpage = logPagePtr.p->logPageWord[ZNEXT_PAGE];
logPagePtr.i = logPagePtr.p->logPageWord[ZNEXT_PAGE];
logFilePtr.p->currentFilepage++;
- ptrCheckGuard(logPagePtr, clogPageFileSize, logPageRecord);
+ ptrCheckGuardErr(logPagePtr, clogPageFileSize, logPageRecord,
+ NDBD_EXIT_SR_REDOLOG);
logPagePtr.p->logPageWord[ZCURR_PAGE_INDEX] = ZPAGE_HEADER_SIZE;
logPartPtr.p->execSrPagesRead--;
logPartPtr.p->execSrPagesExecuted++;
@@ -18274,7 +18341,7 @@ void Dblqh::writeNextLog(Signal* signal)
/* CAN INVOKE THIS SYSTEM CRASH. HOWEVER ONLY */
/* VERY SERIOUS TIMING PROBLEMS. */
/* -------------------------------------------------- */
- systemError(signal);
+ systemError(signal, __LINE__);
}//if
}//if
if (logFilePtr.p->currentMbyte == (ZNO_MBYTES_IN_FILE - 1)) {
@@ -18485,6 +18552,69 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
return;
}
+ Uint32 arg= dumpState->args[0];
+ if(arg == 2304 || arg == 2305)
+ {
+ jam();
+ Uint32 i;
+ GcpRecordPtr gcp; gcp.i = RNIL;
+ for(i = 0; i<4; i++)
+ {
+ logPartPtr.i = i;
+ ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord);
+ ndbout_c("LP %d state: %d WW_Gci: %d gcprec: %d flq: %d currfile: %d tailFileNo: %d logTailMbyte: %d",
+ i,
+ logPartPtr.p->logPartState,
+ logPartPtr.p->waitWriteGciLog,
+ logPartPtr.p->gcprec,
+ logPartPtr.p->firstLogQueue,
+ logPartPtr.p->currentLogfile,
+ logPartPtr.p->logTailFileNo,
+ logPartPtr.p->logTailMbyte);
+
+ if(gcp.i == RNIL && logPartPtr.p->gcprec != RNIL)
+ gcp.i = logPartPtr.p->gcprec;
+
+ LogFileRecordPtr logFilePtr;
+ Uint32 first= logFilePtr.i= logPartPtr.p->firstLogfile;
+ do
+ {
+ ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord);
+ ndbout_c(" file %d(%d) FileChangeState: %d logFileStatus: %d currentMbyte: %d currentFilepage",
+ logFilePtr.p->fileNo,
+ logFilePtr.i,
+ logFilePtr.p->fileChangeState,
+ logFilePtr.p->logFileStatus,
+ logFilePtr.p->currentMbyte,
+ logFilePtr.p->currentFilepage);
+ logFilePtr.i = logFilePtr.p->nextLogFile;
+ } while(logFilePtr.i != first);
+ }
+
+ if(gcp.i != RNIL)
+ {
+ ptrCheckGuard(gcp, cgcprecFileSize, gcpRecord);
+ for(i = 0; i<4; i++)
+ {
+ ndbout_c(" GCP %d file: %d state: %d sync: %d page: %d word: %d",
+ i, gcp.p->gcpFilePtr[i], gcp.p->gcpLogPartState[i],
+ gcp.p->gcpSyncReady[i],
+ gcp.p->gcpPageNo[i],
+ gcp.p->gcpWordNo[i]);
+ }
+ }
+
+ if(arg== 2305)
+ {
+ progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR,
+ "Please report this as a bug. "
+ "Provide as much info as possible, expecially all the "
+ "ndb_*_out.log files, Thanks. "
+ "Shutting down node due to failed handling of GCP_SAVEREQ");
+
+ }
+ }
+
if (dumpState->args[0] == DumpStateOrd::LqhErrorInsert5042 && signal->getLength() == 2)
{
c_error_insert_table_id = dumpState->args[1];
@@ -18493,7 +18623,6 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
TcConnectionrec *regTcConnectionrec = tcConnectionrec;
Uint32 ttcConnectrecFileSize = ctcConnectrecFileSize;
- Uint32 arg = dumpState->args[0];
if(arg == 2306)
{
for(Uint32 i = 0; i<1024; i++)
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index 4488e7500f5..bf6ce7129ba 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -141,6 +141,8 @@
#define ZALREADYEXIST 630
#define ZINCONSISTENTHASHINDEX 892
#define ZNOTUNIQUE 893
+
+#define ZINVALID_KEY 290
#endif
class Dbtc: public SimulatedBlock {
@@ -553,7 +555,7 @@ public:
Uint32 expectedTransIdAI;
AttributeBuffer transIdAI; // For accumulating TransId_AI
- TcIndxReq tcIndxReq;
+ TcKeyReq tcIndxReq;
UintR connectionIndex;
UintR indexReadTcConnect; //
@@ -864,11 +866,11 @@ public:
UintR hashValue; /* THE HASH VALUE USED TO LOCATE FRAGMENT */
Uint8 distributionKeyIndicator;
- Uint8 distributionGroupIndicator;
- Uint8 distributionGroupType;
+ Uint8 m_special_hash; // collation or distribution key
+ Uint8 unused2;
Uint8 lenAiInTckeyreq; /* LENGTH OF ATTRIBUTE INFORMATION IN TCKEYREQ */
- Uint8 distributionKey;
+ Uint8 fragmentDistributionKey; /* DIH generation no */
/**
* EXECUTION MODE OF OPERATION
@@ -892,16 +894,16 @@ public:
// Second 16 byte cache line in second 64 byte cache
// line. Diverse use.
//---------------------------------------------------
- UintR distributionGroup;
+ UintR distributionKey;
UintR nextCacheRec;
- UintR distributionKeySize;
+ UintR unused3;
Uint32 scanInfo;
//---------------------------------------------------
// Third 16 byte cache line in second 64
// byte cache line. Diverse use.
//---------------------------------------------------
- Uint32 scanNode;
+ Uint32 unused4;
Uint32 scanTakeOverInd;
UintR firstKeybuf; /* POINTER THE LINKED LIST OF KEY BUFFERS */
UintR lastKeybuf; /* VARIABLE POINTING TO THE LAST KEY BUFFER */
@@ -949,6 +951,7 @@ public:
typedef Ptr<HostRecord> HostRecordPtr;
/* *********** TABLE RECORD ********************************************* */
+
/********************************************************/
/* THIS RECORD CONTAINS THE CURRENT SCHEMA VERSION OF */
/* ALL TABLES IN THE SYSTEM. */
@@ -959,14 +962,18 @@ public:
Uint8 dropping;
Uint8 tableType;
Uint8 storedTable;
+
+ Uint8 noOfKeyAttr;
+ Uint8 hasCharAttr;
+ Uint8 noOfDistrKeys;
bool checkTable(Uint32 schemaVersion) const {
return enabled && !dropping &&
(table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
}
-
+
Uint32 getErrorCode(Uint32 schemaVersion) const;
-
+
struct DropTable {
Uint32 senderRef;
Uint32 senderData;
@@ -1145,7 +1152,7 @@ public:
Uint32 nextScan;
// Length of expected attribute information
- Uint32 scanAiLength;
+ union { Uint32 scanAiLength; Uint32 m_booked_fragments_count; };
Uint32 scanKeyLen;
@@ -1414,6 +1421,10 @@ private:
void gcpTcfinished(Signal* signal);
void handleGcp(Signal* signal);
void hash(Signal* signal);
+ bool handle_special_hash(Uint32 dstHash[4],
+ Uint32* src, Uint32 srcLen,
+ Uint32 tabPtrI, bool distr);
+
void initApiConnect(Signal* signal);
void initApiConnectRec(Signal* signal,
ApiConnectRecord * const regApiPtr,
@@ -1459,7 +1470,7 @@ private:
void sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr);
void sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len);
void sendlqhkeyreq(Signal* signal, BlockReference TBRef);
- void sendSystemError(Signal* signal);
+ void sendSystemError(Signal* signal, int line);
void sendtckeyconf(Signal* signal, UintR TcommitFlag);
void sendTcIndxConf(Signal* signal, UintR TcommitFlag);
void unlinkApiConnect(Signal* signal);
@@ -1535,8 +1546,8 @@ private:
bool holdOperation = false);
void releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers);
// Generated statement blocks
- void warningHandlerLab(Signal* signal);
- void systemErrorLab(Signal* signal);
+ void warningHandlerLab(Signal* signal, int line);
+ void systemErrorLab(Signal* signal, int line);
void sendSignalErrorRefuseLab(Signal* signal);
void scanTabRefLab(Signal* signal, Uint32 errCode);
void diFcountReqLab(Signal* signal, ScanRecordPtr);
@@ -1671,7 +1682,7 @@ private:
c_scan_count = c_range_scan_count = 0;
}
Uint32 report(Signal* signal){
- signal->theData[0] = EventReport::TransReportCounters;
+ signal->theData[0] = NDB_LE_TransReportCounters;
signal->theData[1] = ctransCount;
signal->theData[2] = ccommitCount;
signal->theData[3] = creadCount;
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
index 2b1f079ea17..7bd308119fc 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
@@ -291,8 +291,19 @@ Dbtc::Dbtc(const class Configuration & conf):
addRecSignal(GSN_ALTER_TAB_REQ, &Dbtc::execALTER_TAB_REQ);
- initData();
-
+ cacheRecord = 0;
+ apiConnectRecord = 0;
+ tcConnectRecord = 0;
+ hostRecord = 0;
+ tableRecord = 0;
+ scanRecord = 0;
+ databufRecord = 0;
+ attrbufRecord = 0;
+ gcpRecord = 0;
+ tcFailRecord = 0;
+ c_apiConTimer = 0;
+ c_apiConTimer_line = 0;
+
#ifdef VM_TRACE
{
void* tmp[] = { &apiConnectptr,
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index ab0981a98ef..9b0818e6e1f 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -20,6 +20,7 @@
#include "md5_hash.hpp"
#include <RefConvert.hpp>
#include <ndb_limits.h>
+#include <my_sys.h>
#include <signaldata/EventReport.hpp>
#include <signaldata/TcKeyReq.hpp>
@@ -63,6 +64,9 @@
#include <signaldata/PackedSignal.hpp>
#include <AttributeHeader.hpp>
#include <signaldata/DictTabInfo.hpp>
+#include <AttributeDescriptor.hpp>
+#include <SectionReader.hpp>
+#include <KeyDescriptor.hpp>
#include <NdbOut.hpp>
#include <DebuggerNames.hpp>
@@ -317,6 +321,10 @@ void Dbtc::execREAD_NODESREF(Signal* signal)
void Dbtc::execTC_SCHVERREQ(Signal* signal)
{
jamEntry();
+ if (! assembleFragments(signal)) {
+ jam();
+ return;
+ }
tabptr.i = signal->theData[0];
ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
tabptr.p->currentSchemaVersion = signal->theData[1];
@@ -324,10 +332,18 @@ void Dbtc::execTC_SCHVERREQ(Signal* signal)
BlockReference retRef = signal->theData[3];
tabptr.p->tableType = (Uint8)signal->theData[4];
BlockReference retPtr = signal->theData[5];
+ Uint32 noOfKeyAttr = signal->theData[6];
+ ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
+
+ const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
+ ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
ndbrequire(tabptr.p->enabled == false);
tabptr.p->enabled = true;
tabptr.p->dropping = false;
+ tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
+ tabptr.p->hasCharAttr = desc->hasCharAttr;
+ tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
signal->theData[0] = tabptr.i;
signal->theData[1] = retPtr;
@@ -597,6 +613,8 @@ void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
+ initData();
+
UintR apiConnect;
UintR tcConnect;
UintR tables;
@@ -1017,7 +1035,7 @@ Dbtc::handleFailedApiNode(Signal* signal,
/*********************************************************************/
// Not implemented yet.
/*********************************************************************/
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
case CS_RESTART:
jam();
@@ -1041,7 +1059,7 @@ Dbtc::handleFailedApiNode(Signal* signal,
/*********************************************************************/
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
} else {
@@ -1380,7 +1398,7 @@ void Dbtc::printState(Signal* signal, int place)
<< " keylen = " << regCachePtr->keylen << endl;
} else {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
}//if
#endif
@@ -1434,7 +1452,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
return;
case 6:
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
case 7:
@@ -1455,7 +1473,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case 10:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 11:
@@ -1486,7 +1504,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
/* PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB */
/* INTERNAL ERROR. */
/********************************************************************/
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
return;
@@ -1499,17 +1517,17 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case 16:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 17:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 18:
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
case 19:
@@ -1518,22 +1536,22 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case 20:
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
case 21:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 22:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 23:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 24:
@@ -1543,7 +1561,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case 25:
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
case 26:
@@ -1551,7 +1569,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
return;
case 27:
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
jam();
return;
@@ -1562,92 +1580,92 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case 29:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 30:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 31:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 32:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 33:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 34:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 35:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 36:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 37:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 38:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 39:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 40:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 41:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 42:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 43:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 44:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 45:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 46:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 47:
@@ -1669,7 +1687,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
case 50:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
case 51:
@@ -1745,7 +1763,7 @@ Dbtc::TCKEY_abort(Signal* signal, int place)
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}
@@ -1802,7 +1820,7 @@ void Dbtc::execKEYINFO(Signal* signal)
return;
default:
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//switch
@@ -2225,11 +2243,10 @@ void Dbtc::hash(Signal* signal)
UintR Tdata2;
UintR Tdata3;
UintR* Tdata32;
- Uint64 Tdata[512];
-
+
CacheRecord * const regCachePtr = cachePtr.p;
- Tdata32 = (UintR*)&Tdata[0];
-
+ Tdata32 = signal->theData;
+
Tdata0 = regCachePtr->keydata[0];
Tdata1 = regCachePtr->keydata[1];
Tdata2 = regCachePtr->keydata[2];
@@ -2255,31 +2272,78 @@ void Dbtc::hash(Signal* signal)
ti += 4;
}//while
}//if
- UintR ThashValue;
- UintR TdistrHashValue;
- ThashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)regCachePtr->keylen);
- if (regCachePtr->distributionGroupIndicator == 1) {
- if (regCachePtr->distributionGroupType == 1) {
- jam();
- TdistrHashValue = (regCachePtr->distributionGroup << 6);
- } else {
- jam();
- Tdata32[0] = regCachePtr->distributionGroup;
- TdistrHashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)1);
- }//if
- } else if (regCachePtr->distributionKeyIndicator == 1) {
+ UintR keylen = (UintR)regCachePtr->keylen;
+ Uint32 distKey = regCachePtr->distributionKeyIndicator;
+
+ Uint32 tmp[4];
+ if(!regCachePtr->m_special_hash)
+ {
+ md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
+ }
+ else
+ {
+ handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
+ }
+
+ thashValue = tmp[0];
+ if (distKey){
jam();
- TdistrHashValue = md5_hash((Uint64*)&Tdata32[0],
- (UintR)regCachePtr->distributionKeySize);
+ tdistrHashValue = regCachePtr->distributionKey;
} else {
jam();
- TdistrHashValue = ThashValue;
+ tdistrHashValue = tmp[1];
}//if
- thashValue = ThashValue;
- tdistrHashValue = TdistrHashValue;
}//Dbtc::hash()
+bool
+Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
+ Uint32 tabPtrI,
+ bool distr)
+{
+ Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ const TableRecord* tabPtrP = &tableRecord[tabPtrI];
+ const bool hasCharAttr = tabPtrP->hasCharAttr;
+ const bool hasDistKeys = tabPtrP->noOfDistrKeys > 0;
+
+ Uint32 *dst = (Uint32*)Tmp;
+ Uint32 dstPos = 0;
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32 * keyPartLenPtr;
+ if(hasCharAttr)
+ {
+ keyPartLenPtr = keyPartLen;
+ dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
+ if (unlikely(dstPos == 0))
+ {
+ goto error;
+ }
+ }
+ else
+ {
+ dst = src;
+ dstPos = srcLen;
+ keyPartLenPtr = 0;
+ }
+
+ md5_hash(dstHash, (Uint64*)dst, dstPos);
+
+ if(distr && hasDistKeys)
+ {
+ jam();
+
+ Uint32 tmp[4];
+ Uint32 len = create_distr_key(tabPtrI, dst, keyPartLenPtr);
+ md5_hash(tmp, (Uint64*)dst, len);
+ dstHash[1] = tmp[1];
+ }
+ return true; // success
+
+error:
+ terrorCode = ZINVALID_KEY;
+ return false;
+}
+
/*
INIT_API_CONNECT_REC
---------------------------
@@ -2672,18 +2736,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TSimpleFlag = tcKeyReq->getSimpleFlag(Treqinfo);
Uint8 TDirtyFlag = tcKeyReq->getDirtyFlag(Treqinfo);
Uint8 TInterpretedFlag = tcKeyReq->getInterpretedFlag(Treqinfo);
- Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
- Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
Uint8 TexecuteFlag = TexecFlag;
regCachePtr->opSimple = TSimpleFlag;
regCachePtr->opExec = TInterpretedFlag;
regTcPtr->dirtyOp = TDirtyFlag;
-
- regCachePtr->distributionGroupIndicator = TDistrGroupFlag;
- regCachePtr->distributionGroupType = TDistrGroupTypeFlag;
- regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
+ regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
//-------------------------------------------------------------
// The next step is to read the upto three conditional words.
@@ -2692,17 +2751,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
{
Uint32 TDistrGHIndex = tcKeyReq->getScanIndFlag(Treqinfo);
- Uint32 TDistrKeyIndex = TDistrGHIndex + TDistrGroupFlag;
+ Uint32 TDistrKeyIndex = TDistrGHIndex;
- Uint32 TscanNode = tcKeyReq->getTakeOverScanNode(TOptionalDataPtr[0]);
Uint32 TscanInfo = tcKeyReq->getTakeOverScanInfo(TOptionalDataPtr[0]);
regCachePtr->scanTakeOverInd = TDistrGHIndex;
- regCachePtr->scanNode = TscanNode;
regCachePtr->scanInfo = TscanInfo;
- regCachePtr->distributionGroup = TOptionalDataPtr[TDistrGHIndex];
- regCachePtr->distributionKeySize = TOptionalDataPtr[TDistrKeyIndex];
+ regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
}
@@ -2736,7 +2792,8 @@ void Dbtc::execTCKEYREQ(Signal* signal)
regCachePtr->keylen = TkeyLength;
regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
regCachePtr->currReclenAi = titcLenAiInTckeyreq;
-
+ regCachePtr->m_special_hash =
+ localTabptr.p->hasCharAttr | (localTabptr.p->noOfDistrKeys > 0);
Tdata1 = TAIDataPtr[0];
Tdata2 = TAIDataPtr[1];
Tdata3 = TAIDataPtr[2];
@@ -2893,7 +2950,15 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
UintR tnoOfStandby;
UintR tnodeinfo;
+ terrorCode = 0;
+
hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
+
+ if (unlikely(terrorCode))
+ {
+ releaseAtErrorLab(signal);
+ return;
+ }
CacheRecord * const regCachePtr = cachePtr.p;
TcConnectRecord * const regTcPtr = tcConnectptr.p;
@@ -2943,6 +3008,15 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
execDIGETNODESREF(signal);
return;
}
+
+ if(ERROR_INSERTED(8050) && signal->theData[3] != getOwnNodeId())
+ {
+ ndbassert(false);
+ signal->theData[1] = 626;
+ execDIGETNODESREF(signal);
+ return;
+ }
+
/****************>>*/
/* DIGETNODESCONF >*/
/* ***************>*/
@@ -2967,7 +3041,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
tnoOfBackup = tnodeinfo & 3;
tnoOfStandby = (tnodeinfo >> 8) & 3;
- regCachePtr->distributionKey = (tnodeinfo >> 16) & 255;
+ regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
if (Toperation == ZREAD) {
if (Tdirty == 1) {
jam();
@@ -2977,7 +3051,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
/* NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION */
/* WITH SIMPLE READS. */
/*-------------------------------------------------------------*/
- arrGuard(tnoOfBackup, 4);
+ arrGuard(tnoOfBackup, MAX_REPLICAS);
UintR Tindex;
UintR TownNode = cownNodeid;
for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
@@ -3032,7 +3106,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
attrinfoDihReceivedLab(signal);
@@ -3057,8 +3131,6 @@ void Dbtc::attrinfoDihReceivedLab(Signal* signal)
CacheRecord * const regCachePtr = cachePtr.p;
TcConnectRecord * const regTcPtr = tcConnectptr.p;
Uint16 Tnode = regTcPtr->tcNodedata[0];
- Uint16 TscanTakeOverInd = regCachePtr->scanTakeOverInd;
- Uint16 TscanNode = regCachePtr->scanNode;
TableRecordPtr localTabptr;
localTabptr.i = regCachePtr->tableref;
@@ -3071,11 +3143,6 @@ void Dbtc::attrinfoDihReceivedLab(Signal* signal)
TCKEY_abort(signal, 58);
return;
}
- if ((TscanTakeOverInd == 1) &&
- (Tnode != TscanNode)) {
- TCKEY_abort(signal, 15);
- return;
- }//if
arrGuard(Tnode, MAX_NDB_NODES);
packLqhkeyreq(signal, calcLqhBlockRef(Tnode));
}//Dbtc::attrinfoDihReceivedLab()
@@ -3107,7 +3174,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
#ifdef ERROR_INSERT
if (ERROR_INSERTED(8002)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
if (ERROR_INSERTED(8007)) {
if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
@@ -3138,7 +3205,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
/* ---------------------------------------------------------------------- */
// Bit16 == 0 since StoredProcedures are not yet supported.
/* ---------------------------------------------------------------------- */
- LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->distributionKey);
+ LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
Tdata10 = 0;
@@ -3374,7 +3441,7 @@ void Dbtc::releaseAttrinfo()
regApiPtr->cachePtr = RNIL;
return;
}//if
- systemErrorLab(0);
+ systemErrorLab(0, __LINE__);
return;
}//Dbtc::releaseAttrinfo()
@@ -3487,7 +3554,7 @@ void Dbtc::execPACKED_SIGNAL(Signal* signal)
Tlength = signal->length();
if (Tlength > 25) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
Uint32* TpackDataPtr;
@@ -3542,7 +3609,7 @@ void Dbtc::execPACKED_SIGNAL(Signal* signal)
Tstep += LqhKeyConf::SignalLength;
break;
default:
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//while
@@ -3620,7 +3687,7 @@ void Dbtc::execLQHKEYCONF(Signal* signal)
#ifdef ERROR_INSERT
if (ERROR_INSERTED(8029)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
if (ERROR_INSERTED(8003)) {
if (regApiPtr->apiConnectstate == CS_STARTED) {
@@ -4105,7 +4172,7 @@ void Dbtc::diverify010Lab(Signal* signal)
signal->theData[0] = apiConnectptr.i;
if (ERROR_INSERTED(8022)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
if (TfirstfreeApiConnectCopy != RNIL) {
seizeApiConnectCopy(signal);
@@ -4453,7 +4520,7 @@ void Dbtc::execCOMMITTED(Signal* signal)
return;
}//if
if (ERROR_INSERTED(8030)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
if (ERROR_INSERTED(8025)) {
SET_ERROR_INSERT_VALUE(8026);
@@ -4507,7 +4574,7 @@ void Dbtc::execCOMMITTED(Signal* signal)
}//if
if (ERROR_INSERTED(8020)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
/*-------------------------------------------------------*/
/* THE ENTIRE TRANSACTION IS NOW COMMITED */
@@ -4554,8 +4621,9 @@ void Dbtc::sendApiCommit(Signal* signal)
}
commitConf->transId1 = regApiPtr->transid[0];
commitConf->transId2 = regApiPtr->transid[1];
-
- sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal, 3, JBB);
+ commitConf->gci = regApiPtr->globalcheckpointid;
+ sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
+ TcCommitConf::SignalLength, JBB);
} else if (regApiPtr->returnsignal == RS_NO_RETURN) {
jam();
} else {
@@ -4747,7 +4815,7 @@ Dbtc::execTC_COMMIT_ACK(Signal* signal){
m_commitAckMarkerHash.release(removedMarker, key);
if (removedMarker.i == RNIL) {
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//if
sendRemoveMarkers(signal, removedMarker.p);
@@ -4809,7 +4877,7 @@ void Dbtc::execCOMPLETED(Signal* signal)
#ifdef ERROR_INSERT
if (ERROR_INSERTED(8031)) {
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
if (ERROR_INSERTED(8019)) {
CLEAR_ERROR_INSERT_VALUE;
@@ -4868,7 +4936,7 @@ void Dbtc::execCOMPLETED(Signal* signal)
}//if
if (ERROR_INSERTED(8021)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
apiConnectptr = localApiConnectptr;
releaseTransResources(signal);
@@ -5252,8 +5320,9 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
commitConf->apiConnectPtr = apiConnectPtr;
commitConf->transId1 = transId1;
commitConf->transId2 = transId2;
-
- sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal, 3, JBB);
+ commitConf->gci = 0;
+ sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
+ TcCommitConf::SignalLength, JBB);
regApiPtr->returnsignal = RS_NO_RETURN;
releaseAbortResources(signal);
@@ -5308,7 +5377,7 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
return;
break;
default:
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//switch
TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
@@ -5321,7 +5390,7 @@ void Dbtc::execTC_COMMITREQ(Signal* signal)
return;
} else /** apiConnectptr.i < capiConnectFilesize */ {
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}
}//Dbtc::execTC_COMMITREQ()
@@ -5417,12 +5486,12 @@ void Dbtc::execTCROLLBACKREQ(Signal* signal)
TC_ROLL_warning:
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
TC_ROLL_system_error:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dbtc::execTCROLLBACKREQ()
@@ -5663,7 +5732,7 @@ void Dbtc::errorReport(Signal* signal, int place)
jam();
break;
}//switch
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Dbtc::errorReport()
@@ -5720,7 +5789,7 @@ void Dbtc::execABORTED(Signal* signal)
}//if
if (ERROR_INSERTED(8024)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
/**
@@ -5893,12 +5962,12 @@ ABORT020:
case OS_ABORT_SENT:
jam();
DEBUG("ABORT_SENT state in abort015Lab(), not expected");
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
default:
jam();
DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
@@ -6014,7 +6083,7 @@ void Dbtc::checkStartTimeout(Signal* signal)
ctimeOutMissedHeartbeats++;
if (ctimeOutMissedHeartbeats > 100){
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}
}
ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
@@ -6203,7 +6272,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
if (((ctcTimer - getApiConTimer(apiConnectptr.i)) > (10 * ctimeOutValue)) &&
((ctcTimer - getApiConTimer(apiConnectptr.i)) > 500)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
break;
case CS_COMMIT_SENT:
@@ -6253,7 +6322,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
jam();
tcConnectptr.i = apiConnectptr.p->currentTcConnect;
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- arrGuard(apiConnectptr.p->currentReplicaNo, 4);
+ arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
ptrCheckGuard(hostptr, chostFilesize, hostRecord);
if (hostptr.p->hostStatus == HS_ALIVE) {
@@ -6279,7 +6348,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
jam();
tcConnectptr.i = apiConnectptr.p->currentTcConnect;
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- arrGuard(apiConnectptr.p->currentReplicaNo, 4);
+ arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
ptrCheckGuard(hostptr, chostFilesize, hostRecord);
if (hostptr.p->hostStatus == HS_ALIVE) {
@@ -6305,7 +6374,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
jam();
tcConnectptr.i = apiConnectptr.p->currentTcConnect;
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
- arrGuard(apiConnectptr.p->currentReplicaNo, 4);
+ arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
ptrCheckGuard(hostptr, chostFilesize, hostRecord);
if (hostptr.p->hostStatus == HS_ALIVE) {
@@ -6351,7 +6420,7 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
/* AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM. */
/*------------------------------------------------------------------*/
DEBUG("State = " << apiConnectptr.p->apiConnectstate);
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
return;
@@ -6480,7 +6549,7 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
// in time to the ABORT signal we will declare it as dead.
/*------------------------------------------------------------------*/
UintR Ti = 0;
- arrGuard(tcConnectptr.p->noOfNodes, 4);
+ arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
jam();
if (tcConnectptr.p->tcNodedata[Ti] != 0) {
@@ -6659,7 +6728,7 @@ void Dbtc::execSCAN_HBREP(Signal* signal)
break;
default:
DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}
@@ -6757,7 +6826,7 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
* version. In a release version we will simply set the time-out to zero.
*-----------------------------------------------------------------------*/
#ifdef VM_TRACE
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
#endif
scanFragptr.p->stopFragTimer();
break;
@@ -6766,7 +6835,7 @@ void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
/*-----------------------------------------------------------------------
* Non-existent state. Crash.
*-----------------------------------------------------------------------*/
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
@@ -7062,7 +7131,6 @@ void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
return;
}
-
checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
}//Dbtc::execTAKE_OVERTCCONF()
@@ -7290,7 +7358,7 @@ void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
arrGuard(TtakeOverInd, MAX_NDB_NODES);
if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
@@ -7411,7 +7479,7 @@ void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//Dbtc::completeTransAtTakeOverDoOne()
@@ -7488,7 +7556,7 @@ void Dbtc::execABORTCONF(Signal* signal)
warningReport(signal, 18);
return;
}//if
- arrGuard(apiConnectptr.p->currentReplicaNo, 4);
+ arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
tnodeid) {
warningReport(signal, 19);
@@ -7504,7 +7572,7 @@ void Dbtc::toAbortHandlingLab(Signal* signal)
do {
if (tcurrentReplicaNo != (Uint8)Z8NIL) {
jam();
- arrGuard(tcurrentReplicaNo, 4);
+ arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
const LqhTransConf::OperationStatus stat =
(LqhTransConf::OperationStatus)
tcConnectptr.p->failData[tcurrentReplicaNo];
@@ -7537,7 +7605,7 @@ void Dbtc::toAbortHandlingLab(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//switch
}//if
@@ -7638,7 +7706,7 @@ void Dbtc::execCOMMITCONF(Signal* signal)
warningReport(signal, 10);
return;
}//if
- arrGuard(apiConnectptr.p->currentReplicaNo, 4);
+ arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
tnodeid) {
warningReport(signal, 11);
@@ -7646,7 +7714,7 @@ void Dbtc::execCOMMITCONF(Signal* signal)
}//if
if (ERROR_INSERTED(8026)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
tcurrentReplicaNo = (Uint8)Z8NIL;
tcConnectptr.p->tcConnectstate = OS_COMMITTED;
@@ -7658,7 +7726,7 @@ void Dbtc::toCommitHandlingLab(Signal* signal)
do {
if (tcurrentReplicaNo != (Uint8)Z8NIL) {
jam();
- arrGuard(tcurrentReplicaNo, 4);
+ arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
case LqhTransConf::InvalidStatus:
jam();
@@ -7696,7 +7764,7 @@ void Dbtc::toCommitHandlingLab(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -7783,7 +7851,7 @@ void Dbtc::execCOMPLETECONF(Signal* signal)
warningReport(signal, 14);
return;
}//if
- arrGuard(apiConnectptr.p->currentReplicaNo, 4);
+ arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
tnodeid) {
warningReport(signal, 15);
@@ -7791,7 +7859,7 @@ void Dbtc::execCOMPLETECONF(Signal* signal)
}//if
if (ERROR_INSERTED(8028)) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
tcConnectptr.p->tcConnectstate = OS_COMPLETED;
tcurrentReplicaNo = (Uint8)Z8NIL;
@@ -7803,7 +7871,7 @@ void Dbtc::toCompleteHandlingLab(Signal* signal)
do {
if (tcurrentReplicaNo != (Uint8)Z8NIL) {
jam();
- arrGuard(tcurrentReplicaNo, 4);
+ arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
case LqhTransConf::InvalidStatus:
jam();
@@ -7906,7 +7974,7 @@ FAF_LOOP:
jam();
if (cfirstfreeApiConnectFail == RNIL) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
seizeApiConnectFail(signal);
@@ -7950,7 +8018,7 @@ void Dbtc::findTcConnectFail(Signal* signal)
jam();
if (cfirstfreeTcConnectFail == RNIL) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//if
seizeTcConnectFail(signal);
@@ -8010,7 +8078,7 @@ void Dbtc::initApiConnectFail(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
apiConnectptr.p->commitAckMarker = RNIL;
if(LqhTransConf::getMarkerFlag(treqinfo)){
@@ -8093,6 +8161,7 @@ void Dbtc::setupFailData(Signal* signal)
case OS_PREPARED:
case OS_COMMITTING:
jam();
+ arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
jam();
/*-------------------------------------------------------------------
@@ -8100,13 +8169,13 @@ void Dbtc::setupFailData(Signal* signal)
* IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
* COMMIT/ABORT DECISION.
*------------------------------------------------------------------*/
- arrGuard(tindex, 4);
tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
}//for
break;
case OS_COMMITTED:
case OS_COMPLETING:
jam();
+ arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
jam();
/*-------------------------------------------------------------------
@@ -8114,25 +8183,24 @@ void Dbtc::setupFailData(Signal* signal)
* IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
* COMPLETE MESSAGE.
*------------------------------------------------------------------*/
- arrGuard(tindex, 4);
tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
}//for
break;
case OS_COMPLETED:
jam();
+ arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
jam();
/*-------------------------------------------------------------------
* KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
* IN THIS CASE ALL LQH'S ARE COMPLETED.
*-------------------------------------------------------------------*/
- arrGuard(tindex, 4);
tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
}//for
break;
default:
jam();
- sendSystemError(signal);
+ sendSystemError(signal, __LINE__);
break;
}//switch
if (tabortInd != ZCOMMIT_SETUP) {
@@ -8219,7 +8287,7 @@ void Dbtc::updateApiStateFail(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
break;
@@ -8242,7 +8310,7 @@ void Dbtc::updateApiStateFail(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
break;
@@ -8252,7 +8320,7 @@ void Dbtc::updateApiStateFail(Signal* signal)
case CS_FAIL_COMMITTING:
case CS_FAIL_COMMITTED:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
case CS_FAIL_PREPARED:
jam();
@@ -8265,7 +8333,7 @@ void Dbtc::updateApiStateFail(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
break;
@@ -8274,7 +8342,7 @@ void Dbtc::updateApiStateFail(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
}//Dbtc::updateApiStateFail()
@@ -8392,14 +8460,14 @@ void Dbtc::releaseAtErrorLab(Signal* signal)
abortErrorLab(signal);
}//Dbtc::releaseAtErrorLab()
-void Dbtc::warningHandlerLab(Signal* signal)
+void Dbtc::warningHandlerLab(Signal* signal, int line)
{
ndbassert(false);
}//Dbtc::warningHandlerLab()
-void Dbtc::systemErrorLab(Signal* signal)
+void Dbtc::systemErrorLab(Signal* signal, int line)
{
- progError(0, 0);
+ progError(line, NDBD_EXIT_NDBREQUIRE);
}//Dbtc::systemErrorLab()
@@ -8500,7 +8568,7 @@ void Dbtc::systemErrorLab(Signal* signal)
void Dbtc::execSCAN_TABREQ(Signal* signal)
{
const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
- const Uint32 reqinfo = scanTabReq->requestInfo;
+ const Uint32 ri = scanTabReq->requestInfo;
const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
@@ -8510,8 +8578,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
Uint32 currSavePointId = 0;
- Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo);
- Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo);
+ Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
+ Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
Uint32 scanParallel = scanConcurrency;
Uint32 errCode;
ScanRecordPtr scanptr;
@@ -8529,7 +8597,7 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
if (apiConnectptr.i >= capiConnectFilesize)
{
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//if
@@ -8596,6 +8664,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
seizeCacheRecord(signal);
cachePtr.p->keylen = keyLen;
cachePtr.p->save1 = 0;
+ cachePtr.p->distributionKey = scanTabReq->distributionKey;
+ cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
scanptr = seizeScanrec(signal);
ndbrequire(transP->apiScanRec == RNIL);
@@ -8682,6 +8752,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
UintR scanParallel,
UintR noOprecPerFrag)
{
+ const UintR ri = scanTabReq->requestInfo;
scanptr.p->scanTcrec = tcConnectptr.i;
scanptr.p->scanApiRec = apiConnectptr.i;
scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
@@ -8694,12 +8765,13 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
scanptr.p->batch_size_rows = noOprecPerFrag;
Uint32 tmp = 0;
- const UintR ri = scanTabReq->requestInfo;
ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
+ ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
+ ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
scanptr.p->scanRequestInfo = tmp;
@@ -8810,14 +8882,43 @@ void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
return;
}
+ scanptr.p->scanNextFragId = 0;
+ scanptr.p->m_booked_fragments_count= 0;
scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
- /*************************************************
- * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
- * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
- ***************************************************/
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanptr.p->scanTableref;
- sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+
+ if(!cachePtr.p->distributionKeyIndicator)
+ {
+ jam();
+ /*************************************************
+ * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
+ * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
+ ***************************************************/
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = scanptr.p->scanTableref;
+ sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+ }
+ else
+ {
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = tabPtr.i;
+ signal->theData[2] = cachePtr.p->distributionKey;
+ EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
+ UintR TerrorIndicator = signal->theData[0];
+ jamEntry();
+ if (TerrorIndicator != 0) {
+ signal->theData[0] = tcConnectptr.i;
+ //signal->theData[1] Contains error
+ execDI_FCOUNTREF(signal);
+ return;
+ }
+
+ UintR Tdata1 = signal->theData[1];
+ scanptr.p->scanNextFragId = Tdata1;
+
+ signal->theData[0] = tcConnectptr.i;
+ signal->theData[1] = 1; // Frag count
+ execDI_FCOUNTCONF(signal);
+ }
return;
}//Dbtc::diFcountReqLab()
@@ -8834,7 +8935,7 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
{
jamEntry();
tcConnectptr.i = signal->theData[0];
- const UintR tfragCount = signal->theData[1];
+ Uint32 tfragCount = signal->theData[1];
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
apiConnectptr.i = tcConnectptr.p->apiConnect;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -8869,24 +8970,17 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
return;
}
- if(scanptr.p->scanParallel > tfragCount){
- jam();
- abortScanLab(signal, scanptr, ZTOO_HIGH_CONCURRENCY_ERROR);
- return;
- }
-
scanptr.p->scanParallel = tfragCount;
scanptr.p->scanNoFrag = tfragCount;
- scanptr.p->scanNextFragId = 0;
scanptr.p->scanState = ScanRecord::RUNNING;
setApiConTimer(apiConnectptr.i, 0, __LINE__);
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)){
+ ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ for (list.first(ptr); !ptr.isNull() && tfragCount;
+ list.next(ptr), tfragCount--){
jam();
ptr.p->lqhBlockref = 0;
@@ -8901,6 +8995,22 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
signal->theData[3] = ptr.p->scanFragId;
sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
}//for
+
+ ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
+ for (; !ptr.isNull();)
+ {
+ ptr.p->m_ops = 0;
+ ptr.p->m_totalLen = 0;
+ ptr.p->m_scan_frag_conf_status = 1;
+ ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
+ ptr.p->stopFragTimer();
+
+ ScanFragRecPtr tmp = ptr;
+ list.next(ptr);
+ list.remove(tmp);
+ queued.add(tmp);
+ scanptr.p->m_queued_count++;
+ }
}//Dbtc::execDI_FCOUNTCONF()
/******************************************************
@@ -9141,7 +9251,7 @@ void Dbtc::execSCAN_FRAGREF(Signal* signal)
transid1 = transid1 | transid2;
if (transid1 != 0) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
/**
@@ -9237,7 +9347,7 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
transid1 = transid1 | transid2;
if (transid1 != 0) {
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
}//if
ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
@@ -9262,7 +9372,7 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
}
if(noCompletedOps == 0 && status != 0 &&
- scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){
+ scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
/**
* Start on next fragment
*/
@@ -9325,7 +9435,7 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
apiConnectptr.i = req->apiConnectPtr;
if (apiConnectptr.i >= capiConnectFilesize) {
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//if
ptrAss(apiConnectptr, apiConnectRecord);
@@ -9432,6 +9542,9 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
*/
jam();
ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
+ jam();
+ ndbassert(scanptr.p->m_booked_fragments_count);
+ scanptr.p->m_booked_fragments_count--;
scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
tcConnectptr.i = scanptr.p->scanTcrec;
@@ -9673,8 +9786,9 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
jam();
ops += 21;
}
-
- Uint32 left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
+
+ int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
+ Uint32 booked = scanPtr.p->m_booked_fragments_count;
ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
@@ -9690,8 +9804,10 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
ScanFragRecPtr curr = ptr; // Remove while iterating...
queued.next(ptr);
- bool done = curr.p->m_scan_frag_conf_status && --left;
-
+ bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
+ if(curr.p->m_scan_frag_conf_status)
+ booked++;
+
* ops++ = curr.p->m_apiPtr;
* ops++ = done ? RNIL : curr.i;
* ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
@@ -9709,8 +9825,10 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
}
}
+ scanPtr.p->m_booked_fragments_count = booked;
if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
- scanPtr.p->m_running_scan_frags.isEmpty()){
+ scanPtr.p->m_running_scan_frags.isEmpty())
+ {
conf->requestInfo = op_count | ScanTabConf::EndOfData;
releaseScanResources(scanPtr);
}
@@ -9969,7 +10087,7 @@ void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -10025,6 +10143,9 @@ void Dbtc::initTable(Signal* signal)
tabptr.p->tableType = 0;
tabptr.p->enabled = false;
tabptr.p->dropping = false;
+ tabptr.p->noOfKeyAttr = 0;
+ tabptr.p->hasCharAttr = 0;
+ tabptr.p->noOfDistrKeys = 0;
}//for
}//Dbtc::initTable()
@@ -10204,7 +10325,7 @@ void Dbtc::releaseAbortResources(Signal* signal)
if(!ok){
jam();
ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
- sendSystemError(signal);
+ sendSystemError(signal, __LINE__);
}//if
}
@@ -10432,9 +10553,9 @@ void Dbtc::sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len)
sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
}//Dbtc::sendKeyinfo()
-void Dbtc::sendSystemError(Signal* signal)
+void Dbtc::sendSystemError(Signal* signal, int line)
{
- progError(0, 0);
+ progError(line, NDBD_EXIT_NDBREQUIRE);
}//Dbtc::sendSystemError()
/* ========================================================================= */
@@ -10455,7 +10576,7 @@ void Dbtc::unlinkGcp(Signal* signal)
* WE ARE TRYING TO REMOVE A GLOBAL CHECKPOINT WHICH WAS NOT THE OLDEST.
* THIS IS A SYSTEM ERROR.
* ------------------------------------------------------------------- */
- sendSystemError(signal);
+ sendSystemError(signal, __LINE__);
}//if
gcpPtr.p->nextGcp = cfirstfreeGcp;
cfirstfreeGcp = gcpPtr.i;
@@ -11228,7 +11349,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
{
jamEntry();
- TcIndxReq * const tcIndxReq = (TcIndxReq *)signal->getDataPtr();
+ TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
const UintR TapiIndex = tcIndxReq->apiConnectPtr;
Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
@@ -11239,7 +11360,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
transPtr.i = TapiIndex;
if (transPtr.i >= capiConnectFilesize) {
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//if
ptrAss(transPtr, apiConnectRecord);
@@ -11279,7 +11400,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
// If operation is readTupleExclusive or updateTuple then read index
// table with exclusive lock
- Uint32 indexLength = TcIndxReq::getIndexLength(tcIndxRequestInfo);
+ Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
Uint32 attrLength = tcIndxReq->attrLen;
indexOp->expectedKeyInfo = indexLength;
Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
@@ -11393,7 +11514,7 @@ void Dbtc::execINDXKEYINFO(Signal* signal)
transPtr.i = TconnectIndex;
if (transPtr.i >= capiConnectFilesize) {
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//if
ptrAss(transPtr, apiConnectRecord);
@@ -11426,7 +11547,7 @@ void Dbtc::execINDXATTRINFO(Signal* signal)
transPtr.i = TconnectIndex;
if (transPtr.i >= capiConnectFilesize) {
jam();
- warningHandlerLab(signal);
+ warningHandlerLab(signal, __LINE__);
return;
}//if
ptrAss(transPtr, apiConnectRecord);
@@ -11584,14 +11705,14 @@ void Dbtc::execTCKEYCONF(Signal* signal)
case(IOS_NOOP): {
jam();
// Should never happen, abort
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
case(IOS_INDEX_ACCESS): {
@@ -11603,14 +11724,14 @@ void Dbtc::execTCKEYCONF(Signal* signal)
case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
jam();
// Double TCKEYCONF, should never happen, abort
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
@@ -11696,8 +11817,8 @@ void Dbtc::execTCKEYREF(Signal* signal)
// Send TCINDXREF
jam();
- TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
ndbassert(regApiPtr->noIndexOp);
regApiPtr->noIndexOp--; // Decrease count
@@ -11706,7 +11827,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
tcIndxRef->transId[1] = tcKeyRef->transId[1];
tcIndxRef->errorCode = tcKeyRef->errorCode;
sendSignal(regApiPtr->ndbapiBlockref,
- GSN_TCINDXREF, signal, TcIndxRef::SignalLength, JBB);
+ GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
return;
}
}
@@ -11773,14 +11894,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
signal->getLength() - TransIdAI::HeaderLength)) {
jam();
// Failed to allocate space for TransIdAI
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4000;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
@@ -11788,14 +11909,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
case(IOS_NOOP): {
jam();
// Should never happen, abort
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
break;
}
@@ -11816,14 +11937,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
#endif
/*
// Too many TRANSID_AI
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
*/
break;
}
@@ -11841,14 +11962,14 @@ void Dbtc::execTRANSID_AI(Signal* signal)
case(IOS_INDEX_OPERATION): {
// Should never receive TRANSID_AI in this state!!
jam();
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
}
@@ -11891,24 +12012,24 @@ void Dbtc::readIndexTable(Signal* signal,
(Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
// Find index table
- if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.indexId)) == NULL) {
+ if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
jam();
// Failed to find index record
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4000;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
tcKeyReq->transId1 = transId1;
tcKeyReq->transId2 = transId2;
tcKeyReq->tableId = indexData->indexId;
tcKeyLength += MIN(keyLength, keyBufSize);
- tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.indexSchemaVersion;
+ tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
TcKeyReq::setOperationType(tcKeyRequestInfo,
opType == ZREAD ? ZREAD : ZREAD_EX);
TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
@@ -12022,7 +12143,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
Uint32 attrBufSize = 5;
Uint32 dataPos = 0;
- TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
+ TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
Uint32 * dataPtr = &tcKeyReq->scanInfo;
Uint32 tcKeyLength = TcKeyReq::StaticLength;
@@ -12033,17 +12154,17 @@ void Dbtc::executeIndexOperation(Signal* signal,
bool moreKeyData = indexOp->transIdAI.first(aiIter);
// Find index table
- if ((indexData = c_theIndexes.getPtr(tcIndxReq->indexId)) == NULL) {
+ if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
jam();
// Failed to find index record
- TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
+ TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
tcIndxRef->transId[0] = regApiPtr->transid[0];
tcIndxRef->transId[1] = regApiPtr->transid[1];
tcIndxRef->errorCode = 4349;
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
- TcIndxRef::SignalLength, JBB);
+ TcKeyRef::SignalLength, JBB);
return;
}
// Find schema version of primary table
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 360710d543b..0b66d9a45bb 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -64,6 +64,7 @@
// DbtupSystemRestart.cpp 26000
// DbtupIndex.cpp 28000
// DbtupDebug.cpp 30000
+// DbtupScan.cpp 32000
//------------------------------------------------------------------
/*
@@ -207,6 +208,8 @@
#define ZTUPLE_DELETED_ERROR 626
#define ZINSERT_ERROR 630
+#define ZINVALID_CHAR_FORMAT 744
+
/* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
#define ZPAGE_STATE_POS 0 /* POSITION OF PAGE STATE */
@@ -493,26 +496,73 @@ struct DiskBufferSegmentInfo {
typedef Ptr<DiskBufferSegmentInfo> DiskBufferSegmentInfoPtr;
struct Fragoperrec {
- bool definingFragment;
+ Uint64 minRows;
+ Uint64 maxRows;
Uint32 nextFragoprec;
Uint32 lqhPtrFrag;
Uint32 fragidFrag;
Uint32 tableidFrag;
Uint32 fragPointer;
Uint32 attributeCount;
- Uint32 freeNullBit;
+ Uint32 currNullBit;
+ Uint32 noOfNullBits;
Uint32 noOfNewAttrCount;
Uint32 charsetIndex;
BlockReference lqhBlockrefFrag;
bool inUse;
+ bool definingFragment;
};
typedef Ptr<Fragoperrec> FragoperrecPtr;
+ // Position for use by scan
+ struct PagePos {
+ Uint32 m_fragId; // "base" fragment id
+ Uint32 m_fragBit; // two fragments in 5.0
+ Uint32 m_pageId;
+ Uint32 m_tupleNo;
+ bool m_match;
+ };
+
+ // Tup scan op (compare Dbtux::ScanOp)
+ struct ScanOp {
+ enum {
+ Undef = 0,
+ First = 1, // before first entry
+ Locked = 4, // at current entry (no lock needed)
+ Next = 5, // looking for next extry
+ Last = 6, // after last entry
+ Invalid = 9 // cannot return REF to LQH currently
+ };
+ Uint16 m_state;
+ Uint16 m_lockwait; // unused
+ Uint32 m_userPtr; // scanptr.i in LQH
+ Uint32 m_userRef;
+ Uint32 m_tableId;
+ Uint32 m_fragId; // "base" fragment id
+ Uint32 m_fragPtrI[2];
+ Uint32 m_transId1;
+ Uint32 m_transId2;
+ PagePos m_scanPos;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+ typedef Ptr<ScanOp> ScanOpPtr;
+ ArrayPool<ScanOp> c_scanOpPool;
+
+ void scanFirst(Signal* signal, ScanOpPtr scanPtr);
+ void scanNext(Signal* signal, ScanOpPtr scanPtr);
+ void scanClose(Signal* signal, ScanOpPtr scanPtr);
+ void releaseScanOp(ScanOpPtr& scanPtr);
+
struct Fragrecord {
Uint32 nextStartRange;
Uint32 currentPageRange;
Uint32 rootPageRange;
Uint32 noOfPages;
+ Uint32 noOfPagesToGrow;
Uint32 emptyPrimPage;
Uint32 firstusedOprec;
@@ -529,6 +579,9 @@ struct Fragrecord {
Uint32 fragTableId;
Uint32 fragmentId;
Uint32 nextfreefrag;
+
+ DLList<ScanOp> m_scanList;
+ Fragrecord(ArrayPool<ScanOp> & scanOpPool) : m_scanList(scanOpPool) {}
};
typedef Ptr<Fragrecord> FragrecordPtr;
@@ -1019,7 +1072,14 @@ public:
* for md5 summing and when returning keyinfo. Returns number of
* words or negative (-terrorCode) on error.
*/
- int tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut);
+ int tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut, bool xfrmFlag);
+
+ /*
+ * ACC reads primary key without headers into an array of words. At
+ * this point in ACC deconstruction, ACC still uses logical references
+ * to fragment and tuple.
+ */
+ int accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag);
/*
* TUX checks if tuple is visible to scan.
@@ -1069,6 +1129,11 @@ private:
void buildIndex(Signal* signal, Uint32 buildPtrI);
void buildIndexReply(Signal* signal, const BuildIndexRec* buildRec);
+ // Tup scan
+ void execACC_SCANREQ(Signal* signal);
+ void execNEXT_SCANREQ(Signal* signal);
+ void execACC_CHECK_SCAN(Signal* signal);
+
//------------------------------------------------------------------
//------------------------------------------------------------------
// Methods to handle execution of TUPKEYREQ + ATTRINFO.
@@ -1618,19 +1683,11 @@ private:
Uint32 attrDescriptor,
Uint32 attrDes2);
-// *****************************************************************
-// Read char routines optionally (tXfrmFlag) apply strxfrm
-// *****************************************************************
-
- bool readCharNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
- bool readCharNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2);
+ bool readBitsNULLable(Uint32* outBuffer, AttributeHeader*, Uint32, Uint32);
+ bool updateBitsNULLable(Uint32* inBuffer, Uint32, Uint32);
+ bool readBitsNotNULL(Uint32* outBuffer, AttributeHeader*, Uint32, Uint32);
+ bool updateBitsNotNULL(Uint32* inBuffer, Uint32, Uint32);
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -1737,8 +1794,7 @@ private:
Uint32* const mainBuffer,
Uint32& noMainWords,
Uint32* const copyBuffer,
- Uint32& noCopyWords,
- bool xfrm);
+ Uint32& noCopyWords);
void sendTrigAttrInfo(Signal* signal,
Uint32* data,
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
index 808cfd33696..8c43de52a75 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
@@ -68,7 +68,7 @@ struct Chunk {
void
Dbtup::reportMemoryUsage(Signal* signal, int incDec){
- signal->theData[0] = EventReport::MemoryUsage;
+ signal->theData[0] = NDB_LE_MemoryUsage;
signal->theData[1] = incDec;
signal->theData[2] = sizeof(Page);
signal->theData[3] = cnoOfAllocatedPages;
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 8171fa65771..f83f21f14d8 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -858,6 +858,8 @@ void Dbtup::sendTUPKEYCONF(Signal* signal,
return;
}//Dbtup::sendTUPKEYCONF()
+#define MAX_READ (sizeof(signal->theData) > MAX_MESSAGE_SIZE ? MAX_MESSAGE_SIZE : sizeof(signal->theData))
+
/* ---------------------------------------------------------------- */
/* ----------------------------- READ ---------------------------- */
/* ---------------------------------------------------------------- */
@@ -878,7 +880,7 @@ int Dbtup::handleReadReq(Signal* signal,
}//if
Uint32 * dst = &signal->theData[25];
- Uint32 dstLen = (sizeof(signal->theData) / 4) - 25;
+ Uint32 dstLen = (MAX_READ / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
;
@@ -888,7 +890,7 @@ int Dbtup::handleReadReq(Signal* signal,
* execute direct
*/
dst = &signal->theData[3];
- dstLen = (sizeof(signal->theData) / 4) - 3;
+ dstLen = (MAX_READ / 4) - 3;
}
if (regOperPtr->interpretedExec != 1) {
@@ -1228,7 +1230,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
const BlockReference sendBref = regOperPtr->recBlockref;
Uint32 * dst = &signal->theData[25];
- Uint32 dstLen = (sizeof(signal->theData) / 4) - 25;
+ Uint32 dstLen = (MAX_READ / 4) - 25;
const Uint32 node = refToNode(sendBref);
if(node != 0 && node != getOwnNodeId()) {
;
@@ -1238,7 +1240,7 @@ int Dbtup::interpreterStartLab(Signal* signal,
* execute direct
*/
dst = &signal->theData[3];
- dstLen = (sizeof(signal->theData) / 4) - 3;
+ dstLen = (MAX_READ / 4) - 3;
}
RtotalLen = RinitReadLen;
@@ -1539,13 +1541,8 @@ int Dbtup::interpreterNextLab(Signal* signal,
// Calculate the number of words of this attribute.
// We allow writes into arrays as long as they fit into the 64 bit
// register size.
- //TEST_MR See to that TattrNoOfWords can be
- // read faster from attribute description.
/* --------------------------------------------------------------- */
- Uint32 TarraySize = (TattrDesc1 >> 16);
- Uint32 TattrLogLen = (TattrDesc1 >> 4) & 0xf;
- Uint32 TattrNoOfBits = TarraySize << TattrLogLen;
- Uint32 TattrNoOfWords = (TattrNoOfBits + 31) >> 5;
+ Uint32 TattrNoOfWords = AttributeDescriptor::getSizeInWords(TattrDesc1);
Uint32 Toptype = operPtr.p->optype;
Uint32 TdataForUpdate[3];
@@ -1827,9 +1824,6 @@ int Dbtup::interpreterNextLab(Signal* signal,
case Interpreter::BRANCH_ATTR_OP_ARG:{
jam();
Uint32 cond = Interpreter::getBinaryCondition(theInstruction);
- Uint32 diff = Interpreter::getArrayLengthDiff(theInstruction);
- Uint32 vchr = Interpreter::isVarchar(theInstruction);
- Uint32 nopad =Interpreter::isNopad(theInstruction);
Uint32 ins2 = TcurrentProgram[TprogramCounter];
Uint32 attrId = Interpreter::getBranchCol_AttrId(ins2) << 16;
Uint32 argLen = Interpreter::getBranchCol_Len(ins2);
@@ -1848,84 +1842,93 @@ int Dbtup::interpreterNextLab(Signal* signal,
}
tmpHabitant = attrId;
}
-
- AttributeHeader ah(tmpArea[0]);
+ // get type
+ attrId >>= 16;
+ Uint32 TattrDescrIndex = tabptr.p->tabDescriptor +
+ (attrId << ZAD_LOG_SIZE);
+ Uint32 TattrDesc1 = tableDescriptor[TattrDescrIndex].tabDescr;
+ Uint32 TattrDesc2 = tableDescriptor[TattrDescrIndex+1].tabDescr;
+ Uint32 typeId = AttributeDescriptor::getType(TattrDesc1);
+ void * cs = 0;
+ if(AttributeOffset::getCharsetFlag(TattrDesc2))
+ {
+ Uint32 pos = AttributeOffset::getCharsetPos(TattrDesc2);
+ cs = tabptr.p->charsetArray[pos];
+ }
+ const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(typeId);
+
+ // get data
+ AttributeHeader ah(tmpArea[0]);
const char* s1 = (char*)&tmpArea[1];
const char* s2 = (char*)&TcurrentProgram[TprogramCounter+1];
- Uint32 attrLen = (4 * ah.getDataSize()) - diff;
- if (vchr) {
-#if NDB_VERSION_MAJOR >= 3
- bool vok = false;
- if (attrLen >= 2) {
- Uint32 vlen = (s1[0] << 8) | s1[1]; // big-endian
- s1 += 2;
- attrLen -= 2;
- if (attrLen >= vlen) {
- attrLen = vlen;
- vok = true;
- }
+ // fixed length in 5.0
+ Uint32 attrLen = AttributeDescriptor::getSizeInBytes(TattrDesc1);
+
+ bool r1_null = ah.isNULL();
+ bool r2_null = argLen == 0;
+ int res1;
+ if (cond != Interpreter::LIKE &&
+ cond != Interpreter::NOT_LIKE) {
+ if (r1_null || r2_null) {
+ // NULL==NULL and NULL<not-NULL
+ res1 = r1_null && r2_null ? 0 : r1_null ? -1 : 1;
+ } else {
+ res1 = (*sqlType.m_cmp)(cs, s1, attrLen, s2, argLen, true);
}
- if (!vok) {
- terrorCode = ZREGISTER_INIT_ERROR;
- tupkeyErrorLab(signal);
- return -1;
- }
-#else
- Uint32 tmp;
- if (attrLen >= 2) {
- unsigned char* ss = (unsigned char*)&s1[attrLen - 2];
- tmp = (ss[0] << 8) | ss[1];
- if (tmp <= attrLen - 2)
- attrLen = tmp;
+ } else {
+ if (r1_null || r2_null) {
+ // NULL like NULL is true (has no practical use)
+ res1 = r1_null && r2_null ? 0 : -1;
+ } else {
+ res1 = (*sqlType.m_like)(cs, s1, attrLen, s2, argLen);
}
- // XXX handle bad data
-#endif
}
- bool res = false;
+ int res = 0;
switch ((Interpreter::BinaryCondition)cond) {
case Interpreter::EQ:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) == 0;
+ res = (res1 == 0);
break;
case Interpreter::NE:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) != 0;
+ res = (res1 != 0);
break;
// note the condition is backwards
case Interpreter::LT:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) > 0;
+ res = (res1 > 0);
break;
case Interpreter::LE:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) >= 0;
+ res = (res1 >= 0);
break;
case Interpreter::GT:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) < 0;
+ res = (res1 < 0);
break;
case Interpreter::GE:
- res = NdbSqlUtil::char_compare(s1, attrLen, s2, argLen, !nopad) <= 0;
+ res = (res1 <= 0);
break;
case Interpreter::LIKE:
- res = NdbSqlUtil::char_like(s1, attrLen, s2, argLen, !nopad);
+ res = (res1 == 0);
break;
case Interpreter::NOT_LIKE:
- res = ! NdbSqlUtil::char_like(s1, attrLen, s2, argLen, !nopad);
+ res = (res1 == 1);
break;
- // XXX handle invalid value
+ // XXX handle invalid value
}
#ifdef TRACE_INTERPRETER
- ndbout_c("cond=%u diff=%d vc=%d nopad=%d attr(%d) = >%.*s<(%d) str=>%.*s<(%d) -> res = %d",
- cond, diff, vchr, nopad,
- attrId >> 16, attrLen, s1, attrLen, argLen, s2, argLen, res);
+ ndbout_c("cond=%u attr(%d)='%.*s'(%d) str='%.*s'(%d) res1=%d res=%d",
+ cond, attrId >> 16,
+ attrLen, s1, attrLen, argLen, s2, argLen, res1, res);
#endif
if (res)
TprogramCounter = brancher(theInstruction, TprogramCounter);
- else {
- Uint32 tmp = (Interpreter::mod4(argLen) >> 2) + 1;
+ else
+ {
+ Uint32 tmp = ((argLen + 3) >> 2) + 1;
TprogramCounter += tmp;
}
break;
}
-
+
case Interpreter::BRANCH_ATTR_EQ_NULL:{
jam();
Uint32 ins2 = TcurrentProgram[TprogramCounter];
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
index af516d53a24..66e98bd2805 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
@@ -75,25 +75,8 @@ Dbtup::Dbtup(const class Configuration & conf)
c_storedProcPool(),
c_buildIndexList(c_buildIndexPool)
{
- Uint32 log_page_size= 0;
BLOCK_CONSTRUCTOR(Dbtup);
- const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndb_mgm_get_int_parameter(p, CFG_DB_UNDO_DATA_BUFFER,
- &log_page_size);
-
- /**
- * Always set page size in half MBytes
- */
- cnoOfUndoPage= (log_page_size / sizeof(UndoPage));
- Uint32 mega_byte_part= cnoOfUndoPage & 15;
- if (mega_byte_part != 0) {
- jam();
- cnoOfUndoPage+= (16 - mega_byte_part);
- }
-
addRecSignal(GSN_DEBUG_SIG, &Dbtup::execDEBUG_SIG);
addRecSignal(GSN_CONTINUEB, &Dbtup::execCONTINUEB);
@@ -137,7 +120,28 @@ Dbtup::Dbtup(const class Configuration & conf)
// Ordered index related
addRecSignal(GSN_BUILDINDXREQ, &Dbtup::execBUILDINDXREQ);
+ // Tup scan
+ addRecSignal(GSN_ACC_SCANREQ, &Dbtup::execACC_SCANREQ);
+ addRecSignal(GSN_NEXT_SCANREQ, &Dbtup::execNEXT_SCANREQ);
+ addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtup::execACC_CHECK_SCAN);
+
initData();
+
+ attrbufrec = 0;
+ checkpointInfo = 0;
+ diskBufferSegmentInfo = 0;
+ fragoperrec = 0;
+ fragrecord = 0;
+ hostBuffer = 0;
+ localLogInfo = 0;
+ operationrec = 0;
+ page = 0;
+ pageRange = 0;
+ pendingFileOpenInfo = 0;
+ restartInfoRecord = 0;
+ tablerec = 0;
+ tableDescriptor = 0;
+ undoPage = 0;
}//Dbtup::Dbtup()
Dbtup::~Dbtup()
@@ -598,6 +602,20 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
theConfiguration.getOwnConfigIterator();
ndbrequire(p != 0);
+ Uint32 log_page_size= 0;
+ ndb_mgm_get_int_parameter(p, CFG_DB_UNDO_DATA_BUFFER,
+ &log_page_size);
+
+ /**
+ * Always set page size in half MBytes
+ */
+ cnoOfUndoPage= (log_page_size / sizeof(UndoPage));
+ Uint32 mega_byte_part= cnoOfUndoPage & 15;
+ if (mega_byte_part != 0) {
+ jam();
+ cnoOfUndoPage+= (16 - mega_byte_part);
+ }
+
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &cnoOfOprec));
@@ -617,12 +635,19 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
&noOfTriggers));
+ Uint32 nScanOp; // use TUX config for now
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
+
+
cnoOfTabDescrRec = (cnoOfTabDescrRec & 0xFFFFFFF0) + 16;
+
+ initRecords();
+
c_storedProcPool.setSize(noOfStoredProc);
c_buildIndexPool.setSize(c_noOfBuildIndexRec);
c_triggerPool.setSize(noOfTriggers);
+ c_scanOpPool.setSize(nScanOp);
- initRecords();
czero = 0;
cminusOne = czero - 1;
clastBitMask = 1;
@@ -644,7 +669,22 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
void Dbtup::initRecords()
{
+ unsigned i;
+
// Records with dynamic sizes
+ page = (Page*)allocRecord("Page",
+ sizeof(Page),
+ cnoOfPage,
+ false);
+
+ undoPage = (UndoPage*)allocRecord("UndoPage",
+ sizeof(UndoPage),
+ cnoOfUndoPage);
+
+ operationrec = (Operationrec*)allocRecord("Operationrec",
+ sizeof(Operationrec),
+ cnoOfOprec);
+
attrbufrec = (Attrbufrec*)allocRecord("Attrbufrec",
sizeof(Attrbufrec),
cnoOfAttrbufrec);
@@ -665,6 +705,11 @@ void Dbtup::initRecords()
fragrecord = (Fragrecord*)allocRecord("Fragrecord",
sizeof(Fragrecord),
cnoOfFragrec);
+
+ for (i = 0; i<cnoOfFragrec; i++) {
+ void * p = &fragrecord[i];
+ new (p) Fragrecord(c_scanOpPool);
+ }
hostBuffer = (HostBuffer*)allocRecord("HostBuffer",
sizeof(HostBuffer),
@@ -674,15 +719,6 @@ void Dbtup::initRecords()
sizeof(LocalLogInfo),
cnoOfParallellUndoFiles);
- operationrec = (Operationrec*)allocRecord("Operationrec",
- sizeof(Operationrec),
- cnoOfOprec);
-
- page = (Page*)allocRecord("Page",
- sizeof(Page),
- cnoOfPage,
- false);
-
pageRange = (PageRange*)allocRecord("PageRange",
sizeof(PageRange),
cnoOfPageRangeRec);
@@ -702,7 +738,7 @@ void Dbtup::initRecords()
sizeof(Tablerec),
cnoOfTablerec);
- for(unsigned i = 0; i<cnoOfTablerec; i++) {
+ for (i = 0; i<cnoOfTablerec; i++) {
void * p = &tablerec[i];
new (p) Tablerec(c_triggerPool);
}
@@ -712,11 +748,6 @@ void Dbtup::initRecords()
sizeof(TableDescriptor),
cnoOfTabDescrRec);
- undoPage = (UndoPage*)allocRecord("UndoPage",
- sizeof(UndoPage),
- cnoOfUndoPage);
-
-
// Initialize BAT for interface to file system
NewVARIABLE* bat = allocateBat(3);
bat[1].WA = &page->pageWord[0];
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index 5a8642c4d2e..ab6e0642e11 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -173,7 +173,7 @@ Dbtup::tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tu
}
int
-Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut)
+Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut, bool xfrmFlag)
{
ljamEntry();
// use own variables instead of globals
@@ -200,8 +200,7 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
operPtr.i = RNIL;
operPtr.p = NULL;
// do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds,
- numAttrs, dataOut, ZNIL, true);
+ int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, xfrmFlag);
// restore globals
tabptr = tabptr_old;
fragptr = fragptr_old;
@@ -229,6 +228,27 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
return ret;
}
+int
+Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag)
+{
+ ljamEntry();
+ // get table
+ TablerecPtr tablePtr;
+ tablePtr.i = tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ // get fragment
+ FragrecordPtr fragPtr;
+ getFragmentrec(fragPtr, fragId, tablePtr.p);
+ // get real page id and tuple offset
+ PagePtr pagePtr;
+ Uint32 pageId = getRealpid(fragPtr.p, fragPageId);
+ ndbrequire((pageIndex & 0x1) == 0);
+ Uint32 pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
+ // use TUX routine - optimize later
+ int ret = tuxReadPk(fragPtr.i, pageId, pageOffset, dataOut, xfrmFlag);
+ return ret;
+}
+
bool
Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId)
{
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
index 73165dc7738..7d2f7d56d48 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
@@ -41,7 +41,8 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
{
ljamEntry();
- if (signal->theData[0] == (Uint32)-1) {
+ TupFragReq* tupFragReq = (TupFragReq*)signal->getDataPtr();
+ if (tupFragReq->userPtr == (Uint32)-1) {
ljam();
abortAddFragOp(signal);
return;
@@ -51,30 +52,34 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
FragrecordPtr regFragPtr;
TablerecPtr regTabPtr;
- Uint32 userptr = signal->theData[0];
- Uint32 userblockref = signal->theData[1];
- Uint32 reqinfo = signal->theData[2];
- regTabPtr.i = signal->theData[3];
- Uint32 noOfAttributes = signal->theData[4];
- Uint32 fragId = signal->theData[5];
- Uint32 noOfNullAttr = signal->theData[7];
- /* Uint32 schemaVersion = signal->theData[8];*/
- Uint32 noOfKeyAttr = signal->theData[9];
+ Uint32 userptr = tupFragReq->userPtr;
+ Uint32 userblockref = tupFragReq->userRef;
+ Uint32 reqinfo = tupFragReq->reqInfo;
+ regTabPtr.i = tupFragReq->tableId;
+ Uint32 noOfAttributes = tupFragReq->noOfAttr;
+ Uint32 fragId = tupFragReq->fragId;
+ Uint32 noOfNullAttr = tupFragReq->noOfNullAttr;
+ /* Uint32 schemaVersion = tupFragReq->schemaVersion;*/
+ Uint32 noOfKeyAttr = tupFragReq->noOfKeyAttr;
- Uint32 noOfNewAttr = (signal->theData[10] & 0xFFFF);
- /* DICT sends number of character sets in upper half */
- Uint32 noOfCharsets = (signal->theData[10] >> 16);
+ Uint32 noOfNewAttr = tupFragReq->noOfNewAttr;
+ Uint32 noOfCharsets = tupFragReq->noOfCharsets;
- Uint32 checksumIndicator = signal->theData[11];
- Uint32 noOfAttributeGroups = signal->theData[12];
- Uint32 globalCheckpointIdIndicator = signal->theData[13];
+ Uint32 checksumIndicator = tupFragReq->checksumIndicator;
+ Uint32 noOfAttributeGroups = tupFragReq->noOfAttributeGroups;
+ Uint32 globalCheckpointIdIndicator = tupFragReq->globalCheckpointIdIndicator;
+
+ Uint64 maxRows =
+ (((Uint64)tupFragReq->maxRowsHigh) << 32) + tupFragReq->maxRowsLow;
+ Uint64 minRows =
+ (((Uint64)tupFragReq->minRowsHigh) << 32) + tupFragReq->minRowsLow;
#ifndef VM_TRACE
// config mismatch - do not crash if release compiled
if (regTabPtr.i >= cnoOfTablerec) {
ljam();
- signal->theData[0] = userptr;
- signal->theData[1] = 800;
+ tupFragReq->userPtr = userptr;
+ tupFragReq->userRef = 800;
sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
return;
}
@@ -83,8 +88,8 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
if (cfirstfreeFragopr == RNIL) {
ljam();
- signal->theData[0] = userptr;
- signal->theData[1] = ZNOFREE_FRAGOP_ERROR;
+ tupFragReq->userPtr = userptr;
+ tupFragReq->userRef = ZNOFREE_FRAGOP_ERROR;
sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
return;
}//if
@@ -96,9 +101,13 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
fragOperPtr.p->fragidFrag = fragId;
fragOperPtr.p->tableidFrag = regTabPtr.i;
fragOperPtr.p->attributeCount = noOfAttributes;
- fragOperPtr.p->freeNullBit = noOfNullAttr;
+ fragOperPtr.p->noOfNullBits = noOfNullAttr;
fragOperPtr.p->noOfNewAttrCount = noOfNewAttr;
fragOperPtr.p->charsetIndex = 0;
+ fragOperPtr.p->currNullBit = 0;
+ // remove in 5.1, 2 fragments per fragment in 5.0
+ fragOperPtr.p->minRows = (minRows + 1)/2;
+ fragOperPtr.p->maxRows = (maxRows + 1)/2;
ndbrequire(reqinfo == ZADDFRAG);
@@ -140,16 +149,6 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
regFragPtr.p->fragmentId = fragId;
regFragPtr.p->checkpointVersion = RNIL;
- Uint32 noAllocatedPages = 2;
- noAllocatedPages = allocFragPages(regFragPtr.p, noAllocatedPages);
-
- if (noAllocatedPages == 0) {
- ljam();
- terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
- fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
- return;
- }//if
-
if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId ||
ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) {
ljam();
@@ -287,8 +286,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
Uint32 attrId = signal->theData[2];
Uint32 attrDescriptor = signal->theData[3];
- // DICT sends extended type (ignored) and charset number
- Uint32 extType = (signal->theData[4] & 0xFF);
+ // DICT sends charset number in upper half
Uint32 csNumber = (signal->theData[4] >> 16);
regTabPtr.i = fragOperPtr.p->tableidFrag;
@@ -309,13 +307,13 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
Uint32 firstTabDesIndex = regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
setTabDescrWord(firstTabDesIndex, attrDescriptor);
Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
- Uint32 nullBitPos = 0; /* Default pos for NOT NULL attributes */
+ Uint32 nullBitPos = fragOperPtr.p->currNullBit;
+ Uint32 bitCount = 0;
+
if (AttributeDescriptor::getNullable(attrDescriptor)) {
if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
- ljam(); /* NULL ATTR */
- fragOperPtr.p->freeNullBit--; /* STORE NULL BIT POSTITION */
- nullBitPos = fragOperPtr.p->freeNullBit;
- ndbrequire(fragOperPtr.p->freeNullBit < ZNIL); /* Check not below zero */
+ ljam(); /* NULL ATTR */
+ fragOperPtr.p->currNullBit++;
}//if
} else {
ljam();
@@ -331,27 +329,40 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
case 2:
{
ljam();
- Uint32 bitsUsed = AttributeDescriptor::getArraySize(attrDescriptor) * (1 << attrLen);
- regTabPtr.p->tupheadsize += ((bitsUsed + 31) >> 5);
- break;
+ if(attrLen != 0)
+ {
+ ljam();
+ Uint32 bitsUsed =
+ AttributeDescriptor::getArraySize(attrDescriptor) * (1 << attrLen);
+ regTabPtr.p->tupheadsize += ((bitsUsed + 31) >> 5);
+ break;
+ }
+ else
+ {
+ ljam();
+ bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ fragOperPtr.p->currNullBit += bitCount;
+ break;
+ }
}
default:
ndbrequire(false);
break;
}//switch
+ if(nullBitPos + bitCount + 1 >= MAX_NULL_BITS)
+ {
+ terrorCode = TupAddAttrRef::TooManyBitsUsed;
+ addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
+ return;
+ }
AttributeOffset::setOffset(attrDes2, attributePos);
AttributeOffset::setNullFlagPos(attrDes2, nullBitPos);
} else {
ndbrequire(false);
}//if
if (csNumber != 0) {
- CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
- if (cs == NULL) {
- ljam();
- terrorCode = TupAddAttrRef::InvalidCharset;
- addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
- return;
- }
+ CHARSET_INFO* cs = all_charsets[csNumber];
+ ndbrequire(cs != NULL);
Uint32 i = 0;
while (i < fragOperPtr.p->charsetIndex) {
ljam();
@@ -375,7 +386,9 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}//if
- if (lastAttr && (fragOperPtr.p->freeNullBit != 0)) {
+ if (lastAttr &&
+ (fragOperPtr.p->currNullBit != fragOperPtr.p->noOfNullBits))
+ {
ljam();
terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
@@ -392,6 +405,27 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
CLEAR_ERROR_INSERT_VALUE;
return;
}
+
+ if (lastAttr)
+ {
+ ljam();
+ Uint32 noRowsPerPage = ZWORDS_ON_PAGE/regTabPtr.p->tupheadsize;
+ Uint32 noAllocatedPages =
+ (fragOperPtr.p->minRows + noRowsPerPage - 1 )/ noRowsPerPage;
+ if (fragOperPtr.p->minRows == 0)
+ noAllocatedPages = 2;
+ else if (noAllocatedPages == 0)
+ noAllocatedPages = 2;
+ noAllocatedPages = allocFragPages(regFragPtr.p, noAllocatedPages);
+
+ if (noAllocatedPages == 0) {
+ ljam();
+ terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
+ addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
+ return;
+ }//if
+ }
+
/* **************************************************************** */
/* ************** TUP_ADD_ATTCONF ****************** */
/* **************************************************************** */
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp b/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
index 1f674876642..acdb73704cb 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp
@@ -332,6 +332,7 @@ void Dbtup::initFragRange(Fragrecord* const regFragPtr)
regFragPtr->rootPageRange = RNIL;
regFragPtr->currentPageRange = RNIL;
regFragPtr->noOfPages = 0;
+ regFragPtr->noOfPagesToGrow = 2;
regFragPtr->nextStartRange = 0;
}//initFragRange()
@@ -393,9 +394,10 @@ Uint32 Dbtup::allocFragPages(Fragrecord* const regFragPtr, Uint32 tafpNoAllocReq
void Dbtup::allocMoreFragPages(Fragrecord* const regFragPtr)
{
- Uint32 noAllocPages = regFragPtr->noOfPages >> 3; // 12.5%
- noAllocPages += regFragPtr->noOfPages >> 4; // 6.25%
+ Uint32 noAllocPages = regFragPtr->noOfPagesToGrow >> 3; // 12.5%
+ noAllocPages += regFragPtr->noOfPagesToGrow >> 4; // 6.25%
noAllocPages += 2;
+ regFragPtr->noOfPagesToGrow += noAllocPages;
/* -----------------------------------------------------------------*/
// We will grow by 18.75% plus two more additional pages to grow
// a little bit quicker in the beginning.
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index 7b642f90a17..8a55777ac05 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -40,7 +40,11 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
if ((AttributeDescriptor::getArrayType(attrDescriptor) == ZNON_ARRAY) ||
(AttributeDescriptor::getArrayType(attrDescriptor) == ZFIXED_ARRAY)) {
if (!AttributeDescriptor::getNullable(attrDescriptor)) {
- if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1) {
+ if (AttributeDescriptor::getSize(attrDescriptor) == 0){
+ ljam();
+ regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNotNULL;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNotNULL;
+ } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1){
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNotNULL;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHOneWordNotNULL;
@@ -55,13 +59,18 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
} else {
ndbrequire(false);
}//if
- // replace read function of char attribute
+ // replace functions for char attribute
if (AttributeOffset::getCharsetFlag(attrOffset)) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readCharNotNULL;
+ regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNotNULL;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNotNULL;
}
} else {
- if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1) {
+ if (AttributeDescriptor::getSize(attrDescriptor) == 0){
+ ljam();
+ regTabPtr->readFunctionArray[i] = &Dbtup::readBitsNULLable;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateBitsNULLable;
+ } else if (AttributeDescriptor::getSizeInWords(attrDescriptor) == 1){
ljam();
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHOneWordNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
@@ -78,10 +87,11 @@ Dbtup::setUpQueryRoutines(Tablerec* const regTabPtr)
regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHZeroWordNULLable;
regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
}//if
- // replace read function of char attribute
+ // replace functions for char attribute
if (AttributeOffset::getCharsetFlag(attrOffset)) {
ljam();
- regTabPtr->readFunctionArray[i] = &Dbtup::readCharNULLable;
+ regTabPtr->readFunctionArray[i] = &Dbtup::readFixedSizeTHManyWordNULLable;
+ regTabPtr->updateFunctionArray[i] = &Dbtup::updateFixedSizeTHManyWordNULLable;
}
}//if
} else if (AttributeDescriptor::getArrayType(attrDescriptor) == ZVAR_ARRAY) {
@@ -329,25 +339,68 @@ Dbtup::readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
Uint32 attrDes2)
{
Uint32 indexBuf = tOutBufIndex;
+ Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
Uint32 attrNoOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 newIndexBuf = indexBuf + attrNoOfWords;
Uint32 maxRead = tMaxRead;
ndbrequire((readOffset + attrNoOfWords - 1) < tCheckOffset);
- if (newIndexBuf <= maxRead) {
- ljam();
- ahOut->setDataSize(attrNoOfWords);
- MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tTupleHeader[readOffset],
- attrNoOfWords);
- tOutBufIndex = newIndexBuf;
- return true;
+ if (! charsetFlag || ! tXfrmFlag) {
+ Uint32 newIndexBuf = indexBuf + attrNoOfWords;
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setDataSize(attrNoOfWords);
+ MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
+ &tTupleHeader[readOffset],
+ attrNoOfWords);
+ tOutBufIndex = newIndexBuf;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ }//if
} else {
ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }//if
+ Tablerec* regTabPtr = tabptr.p;
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ uchar* dstPtr = (uchar*)&outBuffer[indexBuf];
+ const uchar* srcPtr = (uchar*)&tTupleHeader[readOffset];
+ Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
+ ndbrequire(i < regTabPtr->noOfCharsets);
+ CHARSET_INFO* cs = regTabPtr->charsetArray[i];
+ Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ if (ok) {
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ // see comment in DbtcMain.cpp
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ Uint32 maxIndexBuf = indexBuf + (dstLen >> 2);
+ if (maxIndexBuf <= maxRead) {
+ ljam();
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0) {
+ dstPtr[n++] = 0;
+ }
+ Uint32 dstWords = (n >> 2);
+ ahOut->setDataSize(dstWords);
+ Uint32 newIndexBuf = indexBuf + dstWords;
+ ndbrequire(newIndexBuf <= maxRead);
+ tOutBufIndex = newIndexBuf;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ }
+ } else {
+ ljam();
+ terrorCode = ZTUPLE_CORRUPTED_ERROR;
+ }
+ }
+ return false;
}//Dbtup::readFixedSizeTHManyWordNotNULL()
bool
@@ -394,7 +447,6 @@ Dbtup::readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
Uint32 attrDescriptor,
Uint32 attrDes2)
{
-ljam();
if (!nullFlagCheck(attrDes2)) {
ljam();
return readFixedSizeTHManyWordNotNULL(outBuffer,
@@ -555,74 +607,6 @@ Dbtup::readDynSmallVarSize(Uint32* outBuffer,
return false;
}//Dbtup::readDynSmallVarSize()
-
-bool
-Dbtup::readCharNotNULL(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- Uint32 indexBuf = tOutBufIndex;
- Uint32 readOffset = AttributeOffset::getOffset(attrDes2);
- Uint32 attrNoOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- Uint32 newIndexBuf = indexBuf + attrNoOfWords;
- Uint32 maxRead = tMaxRead;
-
- ndbrequire((readOffset + attrNoOfWords - 1) < tCheckOffset);
- if (newIndexBuf <= maxRead) {
- ljam();
- ahOut->setDataSize(attrNoOfWords);
- if (! tXfrmFlag) {
- MEMCOPY_NO_WORDS(&outBuffer[indexBuf],
- &tTupleHeader[readOffset],
- attrNoOfWords);
- } else {
- ljam();
- Tablerec* regTabPtr = tabptr.p;
- Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
- ndbrequire(i < tabptr.p->noOfCharsets);
- // not const in MySQL
- CHARSET_INFO* cs = tabptr.p->charsetArray[i];
- // XXX should strip Uint32 null padding
- const unsigned nBytes = attrNoOfWords << 2;
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)&outBuffer[indexBuf],
- nBytes,
- (const uchar*)&tTupleHeader[readOffset],
- nBytes);
- // pad with ascii spaces
- while (n < nBytes)
- ((uchar*)&outBuffer[indexBuf])[n++] = 0x20;
- }
- tOutBufIndex = newIndexBuf;
- return true;
- } else {
- ljam();
- terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
- return false;
- }
-}
-
-bool
-Dbtup::readCharNULLable(Uint32* outBuffer,
- AttributeHeader* ahOut,
- Uint32 attrDescriptor,
- Uint32 attrDes2)
-{
- if (!nullFlagCheck(attrDes2)) {
- ljam();
- return readCharNotNULL(outBuffer,
- ahOut,
- attrDescriptor,
- attrDes2);
- } else {
- ljam();
- ahOut->setNULL();
- return true;
- }
-}
-
/* ---------------------------------------------------------------------- */
/* THIS ROUTINE IS USED TO UPDATE A NUMBER OF ATTRIBUTES. IT IS */
/* USED BY THE INSERT ROUTINE, THE UPDATE ROUTINE AND IT CAN BE */
@@ -701,22 +685,16 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
Uint32 attrDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
- Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * 1]; // strxfrm_multiply == 1
+ Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset);
if (charsetFlag) {
- Uint32 csPos = AttributeOffset::getCharsetPos(attributeOffset);
- CHARSET_INFO* cs = regTabPtr->charsetArray[csPos];
- Uint32 sizeInBytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
- Uint32 sizeInWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
- const uchar* srcPtr = (uchar*)&updateBuffer[1];
- uchar* dstPtr = (uchar*)&xfrmBuffer[1];
- Uint32 n =
- (*cs->coll->strnxfrm)(cs, dstPtr, sizeInBytes, srcPtr, sizeInBytes);
- // pad with blanks (unlikely) and zeroes to match NDB API behaviour
- while (n < sizeInBytes)
- dstPtr[n++] = 0x20;
- while (n < 4 * sizeInWords)
- dstPtr[n++] = 0;
+ Uint32 csIndex = AttributeOffset::getCharsetPos(attributeOffset);
+ CHARSET_INFO* cs = regTabPtr->charsetArray[csIndex];
+ Uint32 srcPos = 0;
+ Uint32 dstPos = 0;
+ xfrm_attr(attrDescriptor, cs, &updateBuffer[1], srcPos,
+ &xfrmBuffer[1], dstPos, MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY);
+ ahIn.setDataSize(dstPos);
xfrmBuffer[0] = ahIn.m_value;
updateBuffer = xfrmBuffer;
}
@@ -831,6 +809,7 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
Uint32 indexBuf = tInBufIndex;
Uint32 inBufLen = tInBufLen;
Uint32 updateOffset = AttributeOffset::getOffset(attrDes2);
+ Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attrDes2);
AttributeHeader ahIn(inBuffer[indexBuf]);
Uint32 nullIndicator = ahIn.isNULL();
Uint32 noOfWords = AttributeDescriptor::getSizeInWords(attrDescriptor);
@@ -840,6 +819,31 @@ Dbtup::updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
if (newIndex <= inBufLen) {
if (!nullIndicator) {
ljam();
+ if (charsetFlag) {
+ ljam();
+ Tablerec* regTabPtr = tabptr.p;
+ Uint32 typeId = AttributeDescriptor::getType(attrDescriptor);
+ Uint32 bytes = AttributeDescriptor::getSizeInBytes(attrDescriptor);
+ Uint32 i = AttributeOffset::getCharsetPos(attrDes2);
+ ndbrequire(i < regTabPtr->noOfCharsets);
+ // not const in MySQL
+ CHARSET_INFO* cs = regTabPtr->charsetArray[i];
+ int not_used;
+ const char* ssrc = (const char*)&inBuffer[tInBufIndex + 1];
+ Uint32 lb, len;
+ if (! NdbSqlUtil::get_var_length(typeId, ssrc, bytes, lb, len)) {
+ ljam();
+ terrorCode = ZINVALID_CHAR_FORMAT;
+ return false;
+ }
+ // fast fix bug#7340
+ if (typeId != NDB_TYPE_TEXT &&
+ (*cs->cset->well_formed_len)(cs, ssrc + lb, ssrc + lb + len, ZNIL, &not_used) != len) {
+ ljam();
+ terrorCode = ZINVALID_CHAR_FORMAT;
+ return false;
+ }
+ }
tInBufIndex = newIndex;
MEMCOPY_NO_WORDS(&tTupleHeader[updateOffset],
&inBuffer[indexBuf + 1],
@@ -1011,18 +1015,198 @@ Dbtup::read_psuedo(Uint32 attrId, Uint32* outBuffer){
Signal * signal = (Signal*)&tmp;
switch(attrId){
case AttributeHeader::FRAGMENT:
- * outBuffer = operPtr.p->fragId;
+ * outBuffer = operPtr.p->fragId >> 1; // remove "hash" bit
+ return 1;
+ case AttributeHeader::FRAGMENT_MEMORY:
+ {
+ Uint64 tmp = 0;
+ tmp += fragptr.p->noOfPages;
+ {
+ /**
+ * Each fragment is split into 2...get #pages from other as well
+ */
+ Uint32 twin = fragptr.p->fragmentId ^ 1;
+ FragrecordPtr twinPtr;
+ getFragmentrec(twinPtr, twin, tabptr.p);
+ ndbrequire(twinPtr.p != 0);
+ tmp += twinPtr.p->noOfPages;
+ }
+ tmp *= 32768;
+ memcpy(outBuffer,&tmp,8);
+ }
+ return 2;
+ case AttributeHeader::ROW_SIZE:
+ * outBuffer = tabptr.p->tupheadsize << 2;
return 1;
case AttributeHeader::ROW_COUNT:
case AttributeHeader::COMMIT_COUNT:
signal->theData[0] = operPtr.p->userpointer;
signal->theData[1] = attrId;
-
+
EXECUTE_DIRECT(DBLQH, GSN_READ_PSUEDO_REQ, signal, 2);
outBuffer[0] = signal->theData[0];
outBuffer[1] = signal->theData[1];
return 2;
+ case AttributeHeader::RANGE_NO:
+ signal->theData[0] = operPtr.p->userpointer;
+ signal->theData[1] = attrId;
+
+ EXECUTE_DIRECT(DBLQH, GSN_READ_PSUEDO_REQ, signal, 2);
+ outBuffer[0] = signal->theData[0];
+ return 1;
default:
return 0;
}
}
+
+bool
+Dbtup::readBitsNotNULL(Uint32* outBuffer,
+ AttributeHeader* ahOut,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ Uint32 indexBuf = tOutBufIndex;
+ Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
+ Uint32 maxRead = tMaxRead;
+
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setDataSize((bitCount + 31) >> 5);
+ tOutBufIndex = newIndexBuf;
+
+ BitmaskImpl::getField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos,
+ bitCount,
+ outBuffer+indexBuf);
+
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ return false;
+ }//if
+}
+
+bool
+Dbtup::readBitsNULLable(Uint32* outBuffer,
+ AttributeHeader* ahOut,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+
+ Uint32 indexBuf = tOutBufIndex;
+ Uint32 newIndexBuf = indexBuf + ((bitCount + 31) >> 5);
+ Uint32 maxRead = tMaxRead;
+
+ if(BitmaskImpl::get(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos))
+ {
+ ljam();
+ ahOut->setNULL();
+ return true;
+ }
+
+
+ if (newIndexBuf <= maxRead) {
+ ljam();
+ ahOut->setDataSize((bitCount + 31) >> 5);
+ tOutBufIndex = newIndexBuf;
+ BitmaskImpl::getField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos+1,
+ bitCount,
+ outBuffer+indexBuf);
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZTRY_TO_READ_TOO_MUCH_ERROR;
+ return false;
+ }//if
+}
+
+bool
+Dbtup::updateBitsNotNULL(Uint32* inBuffer,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ Uint32 indexBuf = tInBufIndex;
+ Uint32 inBufLen = tInBufLen;
+ AttributeHeader ahIn(inBuffer[indexBuf]);
+ Uint32 nullIndicator = ahIn.isNULL();
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+ Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
+
+ if (newIndex <= inBufLen) {
+ if (!nullIndicator) {
+ BitmaskImpl::setField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos,
+ bitCount,
+ inBuffer+indexBuf+1);
+ tInBufIndex = newIndex;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZNOT_NULL_ATTR;
+ return false;
+ }//if
+ } else {
+ ljam();
+ terrorCode = ZAI_INCONSISTENCY_ERROR;
+ return false;
+ }//if
+ return true;
+}
+
+bool
+Dbtup::updateBitsNULLable(Uint32* inBuffer,
+ Uint32 attrDescriptor,
+ Uint32 attrDes2)
+{
+ Tablerec* const regTabPtr = tabptr.p;
+ AttributeHeader ahIn(inBuffer[tInBufIndex]);
+ Uint32 indexBuf = tInBufIndex;
+ Uint32 nullIndicator = ahIn.isNULL();
+ Uint32 pos = AttributeOffset::getNullFlagPos(attrDes2);
+ Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
+
+ if (!nullIndicator) {
+ BitmaskImpl::clear(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos);
+ BitmaskImpl::setField(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos+1,
+ bitCount,
+ inBuffer+indexBuf+1);
+
+ Uint32 newIndex = indexBuf + 1 + ((bitCount + 31) >> 5);
+ tInBufIndex = newIndex;
+ return true;
+ } else {
+ Uint32 newIndex = tInBufIndex + 1;
+ if (newIndex <= tInBufLen) {
+ ljam();
+ BitmaskImpl::set(regTabPtr->tupNullWords,
+ tTupleHeader+regTabPtr->tupNullIndex,
+ pos);
+
+ tInBufIndex = newIndex;
+ return true;
+ } else {
+ ljam();
+ terrorCode = ZAI_INCONSISTENCY_ERROR;
+ return false;
+ }//if
+ }//if
+}
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
new file mode 100644
index 00000000000..396404faa8c
--- /dev/null
+++ b/ndb/src/kernel/blocks/dbtup/DbtupScan.cpp
@@ -0,0 +1,315 @@
+/* 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 DBTUP_C
+#include "Dbtup.hpp"
+#include <signaldata/AccScan.hpp>
+#include <signaldata/NextScan.hpp>
+
+#undef jam
+#undef jamEntry
+#define jam() { jamLine(32000 + __LINE__); }
+#define jamEntry() { jamEntryLine(32000 + __LINE__); }
+
+void
+Dbtup::execACC_SCANREQ(Signal* signal)
+{
+ jamEntry();
+ const AccScanReq reqCopy = *(const AccScanReq*)signal->getDataPtr();
+ const AccScanReq* const req = &reqCopy;
+ ScanOpPtr scanPtr;
+ scanPtr.i = RNIL;
+ do {
+ // find table and fragments
+ TablerecPtr tablePtr;
+ tablePtr.i = req->tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ FragrecordPtr fragPtr[2];
+ Uint32 fragId = req->fragmentNo << 1;
+ fragPtr[0].i = fragPtr[1].i = RNIL;
+ getFragmentrec(fragPtr[0], fragId | 0, tablePtr.p);
+ getFragmentrec(fragPtr[1], fragId | 1, tablePtr.p);
+ ndbrequire(fragPtr[0].i != RNIL && fragPtr[1].i != RNIL);
+ Fragrecord& frag = *fragPtr[0].p;
+ // seize from pool and link to per-fragment list
+ if (! frag.m_scanList.seize(scanPtr)) {
+ jam();
+ break;
+ }
+ new (scanPtr.p) ScanOp();
+ ScanOp& scan = *scanPtr.p;
+ scan.m_state = ScanOp::First;
+ scan.m_userPtr = req->senderData;
+ scan.m_userRef = req->senderRef;
+ scan.m_tableId = tablePtr.i;
+ scan.m_fragId = frag.fragmentId;
+ scan.m_fragPtrI[0] = fragPtr[0].i;
+ scan.m_fragPtrI[1] = fragPtr[1].i;
+ scan.m_transId1 = req->transId1;
+ scan.m_transId2 = req->transId2;
+ // conf
+ AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = req->senderData;
+ conf->accPtr = scanPtr.i;
+ conf->flag = AccScanConf::ZNOT_EMPTY_FRAGMENT;
+ sendSignal(req->senderRef, GSN_ACC_SCANCONF, signal,
+ AccScanConf::SignalLength, JBB);
+ return;
+ } while (0);
+ if (scanPtr.i != RNIL) {
+ jam();
+ releaseScanOp(scanPtr);
+ }
+ // LQH does not handle REF
+ signal->theData[0] = 0x313;
+ sendSignal(req->senderRef, GSN_ACC_SCANREF, signal, 1, JBB);
+}
+
+void
+Dbtup::execNEXT_SCANREQ(Signal* signal)
+{
+ jamEntry();
+ const NextScanReq reqCopy = *(const NextScanReq*)signal->getDataPtr();
+ const NextScanReq* const req = &reqCopy;
+ ScanOpPtr scanPtr;
+ c_scanOpPool.getPtr(scanPtr, req->accPtr);
+ ScanOp& scan = *scanPtr.p;
+ FragrecordPtr fragPtr;
+ fragPtr.i = scan.m_fragPtrI[0];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ Fragrecord& frag = *fragPtr.p;
+ switch (req->scanFlag) {
+ case NextScanReq::ZSCAN_NEXT:
+ jam();
+ break;
+ case NextScanReq::ZSCAN_NEXT_COMMIT:
+ jam();
+ break;
+ case NextScanReq::ZSCAN_COMMIT:
+ jam();
+ {
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scan.m_userPtr;
+ unsigned signalLength = 1;
+ sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
+ signal, signalLength, JBB);
+ return;
+ }
+ break;
+ case NextScanReq::ZSCAN_CLOSE:
+ jam();
+ scanClose(signal, scanPtr);
+ return;
+ case NextScanReq::ZSCAN_NEXT_ABORT:
+ jam();
+ default:
+ jam();
+ ndbrequire(false);
+ break;
+ }
+ // start looking for next scan result
+ AccCheckScan* checkReq = (AccCheckScan*)signal->getDataPtrSend();
+ checkReq->accPtr = scanPtr.i;
+ checkReq->checkLcpStop = AccCheckScan::ZNOT_CHECK_LCP_STOP;
+ EXECUTE_DIRECT(DBTUP, GSN_ACC_CHECK_SCAN, signal, AccCheckScan::SignalLength);
+ jamEntry();
+}
+
+void
+Dbtup::execACC_CHECK_SCAN(Signal* signal)
+{
+ jamEntry();
+ const AccCheckScan reqCopy = *(const AccCheckScan*)signal->getDataPtr();
+ const AccCheckScan* const req = &reqCopy;
+ ScanOpPtr scanPtr;
+ c_scanOpPool.getPtr(scanPtr, req->accPtr);
+ ScanOp& scan = *scanPtr.p;
+ FragrecordPtr fragPtr;
+ fragPtr.i = scan.m_fragPtrI[0];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ Fragrecord& frag = *fragPtr.p;
+ if (req->checkLcpStop == AccCheckScan::ZCHECK_LCP_STOP) {
+ jam();
+ signal->theData[0] = scan.m_userPtr;
+ signal->theData[1] = true;
+ EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
+ jamEntry();
+ return;
+ }
+ if (scan.m_state == ScanOp::First) {
+ jam();
+ scanFirst(signal, scanPtr);
+ }
+ if (scan.m_state == ScanOp::Next) {
+ jam();
+ scanNext(signal, scanPtr);
+ }
+ if (scan.m_state == ScanOp::Locked) {
+ jam();
+ const PagePos& pos = scan.m_scanPos;
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scan.m_userPtr;
+ conf->accOperationPtr = (Uint32)-1; // no lock returned
+ conf->fragId = frag.fragmentId | pos.m_fragBit;
+ conf->localKey[0] = (pos.m_pageId << MAX_TUPLES_BITS) |
+ (pos.m_tupleNo << 1);
+ conf->localKey[1] = 0;
+ conf->localKeyLength = 1;
+ unsigned signalLength = 6;
+ Uint32 blockNo = refToBlock(scan.m_userRef);
+ EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
+ jamEntry();
+ // next time look for next entry
+ scan.m_state = ScanOp::Next;
+ return;
+ }
+ if (scan.m_state == ScanOp::Last ||
+ scan.m_state == ScanOp::Invalid) {
+ jam();
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scan.m_userPtr;
+ conf->accOperationPtr = RNIL;
+ conf->fragId = RNIL;
+ unsigned signalLength = 3;
+ sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
+ signal, signalLength, JBB);
+ return;
+ }
+ ndbrequire(false);
+}
+
+void
+Dbtup::scanFirst(Signal* signal, ScanOpPtr scanPtr)
+{
+ ScanOp& scan = *scanPtr.p;
+ // set to first fragment, first page, first tuple
+ PagePos& pos = scan.m_scanPos;
+ pos.m_fragId = scan.m_fragId;
+ pos.m_fragBit = 0;
+ pos.m_pageId = 0;
+ pos.m_tupleNo = 0;
+ // just before
+ pos.m_match = false;
+ // let scanNext() do the work
+ scan.m_state = ScanOp::Next;
+}
+
+// TODO optimize this + index build
+void
+Dbtup::scanNext(Signal* signal, ScanOpPtr scanPtr)
+{
+ ScanOp& scan = *scanPtr.p;
+ PagePos& pos = scan.m_scanPos;
+ TablerecPtr tablePtr;
+ tablePtr.i = scan.m_tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ while (true) {
+ // TODO time-slice here after X loops
+ jam();
+ // get fragment
+ if (pos.m_fragBit == 2) {
+ jam();
+ scan.m_state = ScanOp::Last;
+ break;
+ }
+ ndbrequire(pos.m_fragBit <= 1);
+ FragrecordPtr fragPtr;
+ fragPtr.i = scan.m_fragPtrI[pos.m_fragBit];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ Fragrecord& frag = *fragPtr.p;
+ // get page
+ PagePtr pagePtr;
+ if (pos.m_pageId >= frag.noOfPages) {
+ jam();
+ pos.m_fragBit++;
+ pos.m_pageId = 0;
+ pos.m_tupleNo = 0;
+ pos.m_match = false;
+ continue;
+ }
+ Uint32 realPageId = getRealpid(fragPtr.p, pos.m_pageId);
+ pagePtr.i = realPageId;
+ ptrCheckGuard(pagePtr, cnoOfPage, page);
+ const Uint32 pageState = pagePtr.p->pageWord[ZPAGE_STATE_POS];
+ if (pageState != ZTH_MM_FREE &&
+ pageState != ZTH_MM_FULL) {
+ jam();
+ pos.m_pageId++;
+ pos.m_tupleNo = 0;
+ pos.m_match = false;
+ continue;
+ }
+ // get next tuple
+ if (pos.m_match)
+ pos.m_tupleNo++;
+ pos.m_match = true;
+ const Uint32 tupheadsize = tablePtr.p->tupheadsize;
+ Uint32 pageOffset = ZPAGE_HEADER_SIZE + pos.m_tupleNo * tupheadsize;
+ if (pageOffset + tupheadsize > ZWORDS_ON_PAGE) {
+ jam();
+ pos.m_pageId++;
+ pos.m_tupleNo = 0;
+ pos.m_match = false;
+ continue;
+ }
+ // skip over free tuple
+ bool isFree = false;
+ if (pageState == ZTH_MM_FREE) {
+ jam();
+ if ((pagePtr.p->pageWord[pageOffset] >> 16) == tupheadsize) {
+ Uint32 nextTuple = pagePtr.p->pageWord[ZFREELIST_HEADER_POS] >> 16;
+ while (nextTuple != 0) {
+ jam();
+ if (nextTuple == pageOffset) {
+ jam();
+ isFree = true;
+ break;
+ }
+ nextTuple = pagePtr.p->pageWord[nextTuple] & 0xffff;
+ }
+ }
+ }
+ if (isFree) {
+ jam();
+ continue;
+ }
+ // TODO check for operation and return latest in own tx
+ scan.m_state = ScanOp::Locked;
+ break;
+ }
+}
+
+void
+Dbtup::scanClose(Signal* signal, ScanOpPtr scanPtr)
+{
+ NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
+ conf->scanPtr = scanPtr.p->m_userPtr;
+ conf->accOperationPtr = RNIL;
+ conf->fragId = RNIL;
+ unsigned signalLength = 3;
+ sendSignal(scanPtr.p->m_userRef, GSN_NEXT_SCANCONF,
+ signal, signalLength, JBB);
+ releaseScanOp(scanPtr);
+}
+
+void
+Dbtup::releaseScanOp(ScanOpPtr& scanPtr)
+{
+ FragrecordPtr fragPtr;
+ fragPtr.i = scanPtr.p->m_fragPtrI[0];
+ ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
+ fragPtr.p->m_scanList.release(scanPtr);
+}
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
index ed835dc057a..35d1b75e573 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp
@@ -187,7 +187,7 @@ Dbtup::rfrInitRestartInfoLab(Signal* signal, DiskBufferSegmentInfoPtr dbsiPtr)
const Uint32 pageCount = riPtr.p->sriNumDataPages - regFragPtr.p->noOfPages;
if(pageCount > 0){
Uint32 noAllocPages = allocFragPages(regFragPtr.p, pageCount);
- ndbrequire(noAllocPages == pageCount);
+ ndbrequireErr(noAllocPages == pageCount, NDBD_EXIT_SR_OUT_OF_DATAMEMORY);
}//if
ndbrequire(getNoOfPages(regFragPtr.p) == riPtr.p->sriNumDataPages);
@@ -418,7 +418,7 @@ void Dbtup::xlcRestartCompletedLab(Signal* signal)
{
cnoOfLocalLogInfo = 0;
- signal->theData[0] = EventReport::UNDORecordsExecuted;
+ signal->theData[0] = NDB_LE_UNDORecordsExecuted;
signal->theData[1] = DBTUP; // From block
signal->theData[2] = 0; // Total records executed
for (int i = 0; i < 10; i++) {
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
index 59a31475617..6652464dc0f 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp
@@ -607,7 +607,7 @@ void Dbtup::executeTrigger(Signal* signal,
for everybody else.
*/
signal->theData[0] = trigPtr->triggerId;
- signal->theData[1] = regOperPtr->fragId;
+ signal->theData[1] = regOperPtr->fragId >> 1; // send "real" frag id
EXECUTE_DIRECT(BACKUP, GSN_BACKUP_TRIG_REQ, signal, 2);
ljamEntry();
if (signal->theData[0] == 0) {
@@ -622,8 +622,7 @@ void Dbtup::executeTrigger(Signal* signal,
mainBuffer,
noMainWords,
copyBuffer,
- noCopyWords,
- (ref == BACKUP ? false : true))) {
+ noCopyWords)) {
ljam();
return;
}//if
@@ -728,8 +727,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
Uint32* const mainBuffer,
Uint32& noMainWords,
Uint32* const copyBuffer,
- Uint32& noCopyWords,
- bool xfrm)
+ Uint32& noCopyWords)
{
noCopyWords = 0;
noMainWords = 0;
@@ -759,7 +757,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
regTabPtr->noOfKeyAttr,
keyBuffer,
ZATTR_BUFFER_SIZE,
- xfrm);
+ false);
ndbrequire(ret != -1);
noPrimKey= ret;
@@ -802,7 +800,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
numAttrsToRead,
mainBuffer,
ZATTR_BUFFER_SIZE,
- xfrm);
+ false);
ndbrequire(ret != -1);
noMainWords= ret;
} else {
@@ -828,7 +826,7 @@ bool Dbtup::readTriggerInfo(TupTriggerData* const trigPtr,
numAttrsToRead,
copyBuffer,
ZATTR_BUFFER_SIZE,
- xfrm);
+ false);
ndbrequire(ret != -1);
noCopyWords = ret;
diff --git a/ndb/src/kernel/blocks/dbtup/Makefile.am b/ndb/src/kernel/blocks/dbtup/Makefile.am
index e51410e6be3..2d14ad41025 100644
--- a/ndb/src/kernel/blocks/dbtup/Makefile.am
+++ b/ndb/src/kernel/blocks/dbtup/Makefile.am
@@ -18,6 +18,7 @@ libdbtup_a_SOURCES = \
DbtupGen.cpp \
DbtupSystemRestart.cpp \
DbtupIndex.cpp \
+ DbtupScan.cpp \
DbtupDebug.cpp
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 3d78fccb780..d4a44b9e641 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -404,7 +404,7 @@ private:
Uint32 m_accLockOp;
Uint8 m_readCommitted; // no locking
Uint8 m_lockMode;
- Uint8 m_keyInfo;
+ Uint8 m_descending;
ScanBound m_boundMin;
ScanBound m_boundMax;
ScanBound* m_bound[2]; // pointers to above 2
@@ -447,7 +447,7 @@ private:
State m_state;
DictTabInfo::TableType m_tableType;
Uint32 m_tableId;
- Uint16 m_fragOff; // offset for duplicate fragId bits
+ Uint16 unused;
Uint16 m_numFrags;
Uint32 m_fragId[MaxIndexFragments];
Uint32 m_fragPtrI[MaxIndexFragments];
@@ -473,7 +473,7 @@ private:
struct Frag {
Uint32 m_tableId; // copy from index level
Uint32 m_indexId;
- Uint16 m_fragOff;
+ Uint16 unused;
Uint16 m_fragId;
Uint32 m_descPage; // copy from index level
Uint16 m_descOff;
@@ -637,7 +637,7 @@ private:
void execACCKEYREF(Signal* signal);
void execACC_ABORTCONF(Signal* signal);
void scanFirst(ScanOpPtr scanPtr);
- void scanNext(ScanOpPtr scanPtr);
+ void scanNext(ScanOpPtr scanPtr, bool fromMaintReq);
bool scanVisible(ScanOpPtr scanPtr, TreeEnt ent);
void scanClose(Signal* signal, ScanOpPtr scanPtr);
void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
@@ -649,7 +649,9 @@ private:
*/
void searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
void searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
- void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
+ void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, TreePos& treePos);
+ void searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
+ void searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
/*
* DbtuxCmp.cpp
@@ -1028,7 +1030,7 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
m_accLockOp(RNIL),
m_readCommitted(0),
m_lockMode(0),
- m_keyInfo(0),
+ m_descending(0),
m_boundMin(scanBoundPool),
m_boundMax(scanBoundPool),
m_scanPos(),
@@ -1072,7 +1074,6 @@ inline
Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_tableId(RNIL),
m_indexId(RNIL),
- m_fragOff(ZNIL),
m_fragId(ZNIL),
m_descPage(RNIL),
m_descOff(0),
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
index ddab77b97b5..cf815b14c1a 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
@@ -18,24 +18,26 @@
#include "Dbtux.hpp"
/*
- * Search key vs node prefix or entry
+ * Search key vs node prefix or entry.
*
* The comparison starts at given attribute position. The position is
* updated by number of equal initial attributes found. The entry data
* may be partial in which case CmpUnknown may be returned.
+ *
+ * The attributes are normalized and have variable size given in words.
*/
int
Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData 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 = maxlen;
// skip to right position in search key only
for (unsigned i = 0; i < start; i++) {
jam();
searchKey += AttributeHeaderSize + searchKey.ah().getDataSize();
}
+ // number of words of entry data left
+ unsigned len2 = maxlen;
int ret = 0;
while (start < numAttrs) {
if (len2 <= AttributeHeaderSize) {
@@ -47,18 +49,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
if (! searchKey.ah().isNULL()) {
if (! entryData.ah().isNULL()) {
jam();
- // current attribute
+ // verify attribute id
const DescAttr& descAttr = descEnt.m_descAttr[start];
- // full data size
- const unsigned size1 = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
- ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize());
- const unsigned size2 = min(size1, len2);
+ ndbrequire(searchKey.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ // sizes
+ const unsigned size1 = searchKey.ah().getDataSize();
+ const unsigned size2 = min(entryData.ah().getDataSize(), len2);
len2 -= size2;
// compare
NdbSqlUtil::Cmp* const cmp = c_sqlCmp[start];
const Uint32* const p1 = &searchKey[AttributeHeaderSize];
const Uint32* const p2 = &entryData[AttributeHeaderSize];
- ret = (*cmp)(0, p1, p2, size1, size2);
+ const bool full = (maxlen == MaxAttrDataSize);
+ ret = (*cmp)(0, p1, size1 << 2, p2, size2 << 2, full);
if (ret != 0) {
jam();
break;
@@ -99,18 +103,20 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
*
* Following example illustrates this. We are at (a=2, b=3).
*
- * dir bounds strict return
+ * idir bounds strict return
* 0 a >= 2 and b >= 3 no -1
* 0 a >= 2 and b > 3 yes +1
* 1 a <= 2 and b <= 3 no +1
* 1 a <= 2 and b < 3 yes -1
+ *
+ * The attributes are normalized and have variable size given in words.
*/
int
-Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen)
+Dbtux::cmpScanBound(const Frag& frag, unsigned idir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen)
{
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
// direction 0-lower 1-upper
- ndbrequire(dir <= 1);
+ ndbrequire(idir <= 1);
// number of words of data left
unsigned len2 = maxlen;
// in case of no bounds, init last type to something non-strict
@@ -127,21 +133,21 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
if (! boundInfo.ah().isNULL()) {
if (! entryData.ah().isNULL()) {
jam();
- // current attribute
- const unsigned index = boundInfo.ah().getAttributeId();
+ // verify attribute id
+ const Uint32 index = boundInfo.ah().getAttributeId();
ndbrequire(index < frag.m_numAttrs);
const DescAttr& descAttr = descEnt.m_descAttr[index];
ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
- // full data size
+ // sizes
const unsigned size1 = boundInfo.ah().getDataSize();
- ndbrequire(size1 != 0 && size1 == entryData.ah().getDataSize());
- const unsigned size2 = min(size1, len2);
+ const unsigned size2 = min(entryData.ah().getDataSize(), len2);
len2 -= size2;
// compare
NdbSqlUtil::Cmp* const cmp = c_sqlCmp[index];
const Uint32* const p1 = &boundInfo[AttributeHeaderSize];
const Uint32* const p2 = &entryData[AttributeHeaderSize];
- int ret = (*cmp)(0, p1, p2, size1, size2);
+ const bool full = (maxlen == MaxAttrDataSize);
+ int ret = (*cmp)(0, p1, size1 << 2, p2, size2 << 2, full);
if (ret != 0) {
jam();
return ret;
@@ -165,5 +171,5 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigne
}
// all attributes were equal
const int strict = (type & 0x1);
- return (dir == 0 ? (strict == 0 ? -1 : +1) : (strict == 0 ? +1 : -1));
+ return (idir == 0 ? (strict == 0 ? -1 : +1) : (strict == 0 ? +1 : -1));
}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index 1e1b0d1d5b6..ed29dc57915 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -340,14 +340,14 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
out << " [savePointId " << dec << scan.m_savePointId << "]";
out << " [accLockOp " << hex << scan.m_accLockOp << "]";
out << " [accLockOps";
- for (unsigned i = 0; i < Dbtux::MaxAccLockOps; i++) {
+ for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
if (scan.m_accLockOps[i] != RNIL)
out << " " << hex << scan.m_accLockOps[i];
}
out << "]";
out << " [readCommitted " << dec << scan.m_readCommitted << "]";
out << " [lockMode " << dec << scan.m_lockMode << "]";
- out << " [keyInfo " << dec << scan.m_keyInfo << "]";
+ out << " [descending " << dec << scan.m_descending << "]";
out << " [pos " << scan.m_scanPos << "]";
out << " [ent " << scan.m_scanEnt << "]";
for (unsigned i = 0; i <= 1; i++) {
@@ -370,7 +370,6 @@ operator<<(NdbOut& out, const Dbtux::Index& index)
{
out << "[Index " << hex << &index;
out << " [tableId " << dec << index.m_tableId << "]";
- out << " [fragOff " << dec << index.m_fragOff << "]";
out << " [numFrags " << dec << index.m_numFrags << "]";
for (unsigned i = 0; i < index.m_numFrags; i++) {
out << " [frag " << dec << i << " ";
@@ -393,7 +392,6 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
out << "[Frag " << hex << &frag;
out << " [tableId " << dec << frag.m_tableId << "]";
out << " [indexId " << dec << frag.m_indexId << "]";
- out << " [fragOff " << dec << frag.m_fragOff << "]";
out << " [fragId " << dec << frag.m_fragId << "]";
out << " [descPage " << hex << frag.m_descPage << "]";
out << " [descOff " << dec << frag.m_descOff << "]";
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 8990d6c86b6..5640fdf2899 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -217,6 +217,7 @@ Dbtux::setKeyAttrs(const Frag& frag)
const unsigned numAttrs = frag.m_numAttrs;
const DescEnt& descEnt = getDescEnt(frag.m_descPage, frag.m_descOff);
for (unsigned i = 0; i < numAttrs; i++) {
+ jam();
const DescAttr& descAttr = descEnt.m_descAttr[i];
Uint32 size = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
// set attr id and fixed size
@@ -244,6 +245,26 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
jamEntry();
// TODO handle error
ndbrequire(ret > 0);
+#ifdef VM_TRACE
+ if (debugFlags & (DebugMaint | DebugScan)) {
+ debugOut << "readKeyAttrs:" << endl;
+ ConstData data = keyData;
+ Uint32 totalSize = 0;
+ for (Uint32 i = start; i < frag.m_numAttrs; i++) {
+ Uint32 attrId = data.ah().getAttributeId();
+ Uint32 dataSize = data.ah().getDataSize();
+ debugOut << i << " attrId=" << attrId << " size=" << dataSize;
+ data += 1;
+ for (Uint32 j = 0; j < dataSize; j++) {
+ debugOut << " " << hex << data[0];
+ data += 1;
+ }
+ debugOut << endl;
+ totalSize += 1 + dataSize;
+ }
+ ndbassert((int)totalSize == ret);
+ }
+#endif
}
void
@@ -251,7 +272,7 @@ Dbtux::readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize)
{
const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[ent.m_fragBit];
const TupLoc tupLoc = ent.m_tupLoc;
- int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), pkData);
+ int ret = c_tup->tuxReadPk(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), pkData, true);
jamEntry();
// TODO handle error
ndbrequire(ret > 0);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 30afb51e7d7..4b568badc67 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -57,9 +57,8 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
c_indexPool.getPtr(indexPtr, req->indexId);
ndbrequire(indexPtr.p->m_tableId == req->tableId);
// get base fragment id and extra bits
- const Uint32 fragOff = indexPtr.p->m_fragOff;
- const Uint32 fragId = req->fragId & ((1 << fragOff) - 1);
- const Uint32 fragBit = req->fragId >> fragOff;
+ const Uint32 fragId = req->fragId & ~1;
+ const Uint32 fragBit = req->fragId & 1;
// get the fragment
FragPtr fragPtr;
fragPtr.i = RNIL;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index b7526593a08..c85c8384081 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -16,6 +16,7 @@
#define DBTUX_META_CPP
#include "Dbtux.hpp"
+#include <my_sys.h>
/*
* Create index.
@@ -84,7 +85,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
new (fragPtr.p) Frag(c_scanOpPool);
fragPtr.p->m_tableId = req->primaryTableId;
fragPtr.p->m_indexId = req->tableId;
- 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
@@ -112,7 +112,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_state = Index::Defining;
indexPtr.p->m_tableType = (DictTabInfo::TableType)req->tableType;
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
@@ -128,7 +127,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_state == Index::Defining &&
indexPtr.p->m_tableType == (DictTabInfo::TableType)req->tableType &&
indexPtr.p->m_tableId == req->primaryTableId &&
- indexPtr.p->m_fragOff == req->fragOff &&
indexPtr.p->m_numAttrs == req->noOfAttr);
}
// copy metadata address to each fragment
@@ -203,7 +201,7 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
DescAttr& descAttr = descEnt.m_descAttr[attrId];
descAttr.m_attrDesc = req->attrDescriptor;
descAttr.m_primaryAttrId = req->primaryAttrId;
- descAttr.m_typeId = req->extTypeInfo & 0xFF;
+ descAttr.m_typeId = AttributeDescriptor::getType(req->attrDescriptor);
descAttr.m_charset = (req->extTypeInfo >> 16);
#ifdef VM_TRACE
if (debugFlags & DebugMeta) {
@@ -218,17 +216,16 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
errorCode = TuxAddAttrRef::InvalidAttributeType;
break;
}
-#ifdef dbtux_uses_charset
if (descAttr.m_charset != 0) {
- CHARSET_INFO *cs = get_charset(descAttr.m_charset, MYF(0));
- // here use the non-binary type
- if (! NdbSqlUtil::usable_in_ordered_index(descAttr.m_typeId, cs)) {
+ uint err;
+ CHARSET_INFO *cs = all_charsets[descAttr.m_charset];
+ ndbrequire(cs != 0);
+ if ((err = NdbSqlUtil::check_column_for_ordered_index(descAttr.m_typeId, cs))) {
jam();
- errorCode = TuxAddAttrRef::InvalidCharset;
+ errorCode = (TuxAddAttrRef::ErrorCode) err;
break;
}
}
-#endif
const bool lastAttr = (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd);
if (ERROR_INSERTED(12003) && fragOpPtr.p->m_fragNo == 0 && attrId == 0 ||
ERROR_INSERTED(12004) && fragOpPtr.p->m_fragNo == 0 && lastAttr ||
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
index 9f9d4cb68e3..68a3e78ce9e 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
@@ -502,7 +502,7 @@ Dbtux::moveScanList(NodeHandle& node, unsigned pos)
debugOut << "At pos=" << pos << " " << node << endl;
}
#endif
- scanNext(scanPtr);
+ scanNext(scanPtr, true);
ndbrequire(! (scanPos.m_loc == node.m_loc && scanPos.m_pos == pos));
}
scanPtr.i = nextPtrI;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index 8677ae741b3..a61b7c1f5ca 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -16,6 +16,7 @@
#define DBTUX_SCAN_CPP
#include "Dbtux.hpp"
+#include <my_sys.h>
void
Dbtux::execACC_SCANREQ(Signal* signal)
@@ -34,7 +35,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
fragPtr.i = RNIL;
for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
jam();
- if (indexPtr.p->m_fragId[i] == req->fragmentNo) {
+ if (indexPtr.p->m_fragId[i] == req->fragmentNo << 1) {
jam();
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
break;
@@ -43,7 +44,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
ndbrequire(fragPtr.i != RNIL);
Frag& frag = *fragPtr.p;
// must be normal DIH/TC fragment
- ndbrequire(frag.m_fragId < (1 << frag.m_fragOff));
TreeHead& tree = frag.m_tree;
// check for empty fragment
if (tree.m_root == NullTupLoc) {
@@ -74,18 +74,18 @@ Dbtux::execACC_SCANREQ(Signal* signal)
scanPtr.p->m_savePointId = req->savePointId;
scanPtr.p->m_readCommitted = AccScanReq::getReadCommittedFlag(req->requestInfo);
scanPtr.p->m_lockMode = AccScanReq::getLockMode(req->requestInfo);
- scanPtr.p->m_keyInfo = AccScanReq::getKeyinfoFlag(req->requestInfo);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Seize scan " << scanPtr.i << " " << *scanPtr.p << endl;
- }
-#endif
+ scanPtr.p->m_descending = AccScanReq::getDescendingFlag(req->requestInfo);
/*
* readCommitted lockMode keyInfo
* 1 0 0 - read committed (no lock)
* 0 0 0 - read latest (read lock)
* 0 1 1 - read exclusive (write lock)
*/
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Seize scan " << scanPtr.i << " " << *scanPtr.p << endl;
+ }
+#endif
// conf
AccScanConf* const conf = (AccScanConf*)signal->getDataPtrSend();
conf->scanPtr = req->senderData;
@@ -114,50 +114,100 @@ Dbtux::execACC_SCANREQ(Signal* signal)
* keys and that all but possibly last bound is non-strict.
*
* Finally save the sets of lower and upper bounds (i.e. start key and
- * end key). Full bound type (< 4) is included but only the strict bit
- * is used since lower and upper have now been separated.
+ * end key). Full bound type is included but only the strict bit is
+ * used since lower and upper have now been separated.
*/
void
Dbtux::execTUX_BOUND_INFO(Signal* signal)
{
jamEntry();
- struct BoundInfo {
- int type;
- unsigned offset;
- unsigned size;
- };
- TuxBoundInfo* const sig = (TuxBoundInfo*)signal->getDataPtrSend();
- const TuxBoundInfo reqCopy = *(const TuxBoundInfo*)sig;
- const TuxBoundInfo* const req = &reqCopy;
// get records
+ TuxBoundInfo* const sig = (TuxBoundInfo*)signal->getDataPtrSend();
+ const TuxBoundInfo* const req = (const TuxBoundInfo*)sig;
ScanOp& scan = *c_scanOpPool.getPtr(req->tuxScanPtrI);
- Index& index = *c_indexPool.getPtr(scan.m_indexId);
- // collect lower and upper bounds
+ const Index& index = *c_indexPool.getPtr(scan.m_indexId);
+ const DescEnt& descEnt = getDescEnt(index.m_descPage, index.m_descOff);
+ // collect normalized lower and upper bounds
+ struct BoundInfo {
+ int type2; // with EQ -> LE/GE
+ Uint32 offset; // offset in xfrmData
+ Uint32 size;
+ };
BoundInfo boundInfo[2][MaxIndexAttributes];
+ const unsigned dstSize = 1024 * MAX_XFRM_MULTIPLY;
+ Uint32 xfrmData[dstSize];
+ Uint32 dstPos = 0;
// largest attrId seen plus one
Uint32 maxAttrId[2] = { 0, 0 };
- unsigned offset = 0;
- const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength;
// walk through entries
+ const Uint32* const data = (Uint32*)sig + TuxBoundInfo::SignalLength;
+ Uint32 offset = 0;
while (offset + 2 <= req->boundAiLength) {
jam();
const unsigned type = data[offset];
- if (type > 4) {
- jam();
- scan.m_state = ScanOp::Invalid;
- sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
- return;
- }
const AttributeHeader* ah = (const AttributeHeader*)&data[offset + 1];
const Uint32 attrId = ah->getAttributeId();
const Uint32 dataSize = ah->getDataSize();
- if (attrId >= index.m_numAttrs) {
+ if (type > 4 || attrId >= index.m_numAttrs || dstPos + 2 + dataSize > dstSize) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
return;
}
+ // copy header
+ xfrmData[dstPos + 0] = data[offset + 0];
+ xfrmData[dstPos + 1] = data[offset + 1];
+ // copy bound value
+ Uint32 dstWords = 0;
+ if (! ah->isNULL()) {
+ jam();
+ const DescAttr& descAttr = descEnt.m_descAttr[attrId];
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(descAttr.m_attrDesc);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ if (srcWords != dataSize) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::InvalidAttrInfo;
+ return;
+ }
+ uchar* dstPtr = (uchar*)&xfrmData[dstPos + 2];
+ const uchar* srcPtr = (const uchar*)&data[offset + 2];
+ if (descAttr.m_charset == 0) {
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ } else {
+ jam();
+ Uint32 typeId = descAttr.m_typeId;
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ if (! ok) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::InvalidCharFormat;
+ return;
+ }
+ CHARSET_INFO* cs = all_charsets[descAttr.m_charset];
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ // see comment in DbtcMain.cpp
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ if (dstLen > ((dstSize - dstPos) << 2)) {
+ jam();
+ scan.m_state = ScanOp::Invalid;
+ sig->errorCode = TuxBoundInfo::TooMuchAttrInfo;
+ return;
+ }
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0) {
+ dstPtr[n++] = 0;
+ }
+ dstWords = n / 4;
+ }
+ }
for (unsigned j = 0; j <= 1; j++) {
+ jam();
// check if lower/upper bit matches
const unsigned luBit = (j << 1);
if ((type & 0x2) != luBit && type != 4)
@@ -166,29 +216,35 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
const unsigned type2 = (type & 0x1) | luBit;
// fill in any gap
while (maxAttrId[j] <= attrId) {
+ jam();
BoundInfo& b = boundInfo[j][maxAttrId[j]++];
- b.type = -1;
+ b.type2 = -1;
}
BoundInfo& b = boundInfo[j][attrId];
- if (b.type != -1) {
- // compare with previous bound
- if (b.type != (int)type2 ||
- b.size != 2 + dataSize ||
- memcmp(&data[b.offset + 2], &data[offset + 2], dataSize << 2) != 0) {
+ if (b.type2 != -1) {
+ // compare with previously defined bound
+ if (b.type2 != (int)type2 ||
+ b.size != 2 + dstWords ||
+ memcmp(&xfrmData[b.offset + 2], &xfrmData[dstPos + 2], dstWords << 2) != 0) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidBounds;
return;
}
} else {
+ // fix length
+ AttributeHeader* ah = (AttributeHeader*)&xfrmData[dstPos + 1];
+ ah->setDataSize(dstWords);
// enter new bound
- b.type = type2;
- b.offset = offset;
- b.size = 2 + dataSize;
+ jam();
+ b.type2 = type2;
+ b.offset = dstPos;
+ b.size = 2 + dstWords;
}
}
// jump to next
offset += 2 + dataSize;
+ dstPos += 2 + dstWords;
}
if (offset != req->boundAiLength) {
jam();
@@ -202,13 +258,13 @@ Dbtux::execTUX_BOUND_INFO(Signal* signal)
jam();
const BoundInfo& b = boundInfo[j][i];
// check for gap or strict bound before last
- if (b.type == -1 || (i + 1 < maxAttrId[j] && (b.type & 0x1))) {
+ if (b.type2 == -1 || (i + 1 < maxAttrId[j] && (b.type2 & 0x1))) {
jam();
scan.m_state = ScanOp::Invalid;
sig->errorCode = TuxBoundInfo::InvalidBounds;
return;
}
- bool ok = scan.m_bound[j]->append(&data[b.offset], b.size);
+ bool ok = scan.m_bound[j]->append(&xfrmData[b.offset], b.size);
if (! ok) {
jam();
scan.m_state = ScanOp::Invalid;
@@ -354,7 +410,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL; // no tuple returned
- conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ conf->fragId = frag.m_fragId | ent.m_fragBit;
unsigned signalLength = 3;
// if TC has ordered scan close, it will be detected here
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
@@ -374,7 +430,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (scan.m_state == ScanOp::Next) {
jam();
// look for next
- scanNext(scanPtr);
+ scanNext(scanPtr, false);
}
// for reading tuple key in Current or Locked state
Data pkData = c_dataBuffer;
@@ -397,7 +453,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
lockReq->userPtr = scanPtr.i;
lockReq->userRef = reference();
lockReq->tableId = scan.m_tableId;
- lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ lockReq->fragId = frag.m_fragId | ent.m_fragBit;
lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
const Uint32* const buf32 = static_cast<Uint32*>(pkData);
const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
@@ -474,13 +530,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
jam();
// read keys if not already done (uses signal)
const TreeEnt ent = scan.m_scanEnt;
- if (scan.m_keyInfo) {
- jam();
- if (pkSize == 0) {
- jam();
- readTablePk(frag, ent, pkData, pkSize);
- }
- }
// conf signal
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
@@ -496,21 +545,12 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
accLockOp = (Uint32)-1;
}
conf->accOperationPtr = accLockOp;
- conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ conf->fragId = frag.m_fragId | ent.m_fragBit;
conf->localKey[0] = getTupAddr(frag, ent);
conf->localKey[1] = 0;
conf->localKeyLength = 1;
unsigned signalLength = 6;
// add key info
- if (scan.m_keyInfo) {
- jam();
- conf->keyLength = pkSize;
- // piggy-back first 4 words of key data
- for (unsigned i = 0; i < 4; i++) {
- conf->key[i] = i < pkSize ? pkData[i] : 0;
- }
- signalLength = 11;
- }
if (! scan.m_readCommitted) {
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
@@ -518,24 +558,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
Uint32 blockNo = refToBlock(scan.m_userRef);
EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
}
- // send rest of key data
- if (scan.m_keyInfo && pkSize > 4) {
- unsigned total = 4;
- while (total < pkSize) {
- jam();
- 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], &pkData[total], length << 2);
- sendSignal(scan.m_userRef, GSN_ACC_SCAN_INFO24,
- signal, 4 + length, JBB);
- total += length;
- }
- }
// next time look for next entry
scan.m_state = ScanOp::Next;
return;
@@ -687,8 +709,10 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
TreeHead& tree = frag.m_tree;
// set up index keys for this operation
setKeyAttrs(frag);
- // unpack lower bound into c_dataBuffer
- const ScanBound& bound = *scan.m_bound[0];
+ // scan direction 0, 1
+ const unsigned idir = scan.m_descending;
+ // unpack start key into c_dataBuffer
+ const ScanBound& bound = *scan.m_bound[idir];
ScanBoundIterator iter;
bound.first(iter);
for (unsigned j = 0; j < bound.getSize(); j++) {
@@ -696,11 +720,10 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
c_dataBuffer[j] = *iter.data;
bound.next(iter);
}
- // search for scan start position
TreePos treePos;
- searchToScan(frag, c_dataBuffer, scan.m_boundCnt[0], treePos);
+ searchToScan(frag, c_dataBuffer, scan.m_boundCnt[idir], scan.m_descending, treePos);
if (treePos.m_loc == NullTupLoc) {
- // empty tree
+ // empty result set
jam();
scan.m_state = ScanOp::Last;
return;
@@ -718,7 +741,8 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
* Move to next entry. The scan is already linked to some node. When
* we leave, if an entry was found, it will be linked to a possibly
* different node. The scan has a position, and a direction which tells
- * from where we came to this position. This is one of:
+ * from where we came to this position. This is one of (all comments
+ * are in terms of ascending scan):
*
* 0 - up from left child (scan this node next)
* 1 - up from right child (proceed to parent)
@@ -730,7 +754,7 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
* re-organizations need not worry about scan direction.
*/
void
-Dbtux::scanNext(ScanOpPtr scanPtr)
+Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
{
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
@@ -743,8 +767,11 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
ndbrequire(scan.m_state != ScanOp::Locked);
// set up index keys for this operation
setKeyAttrs(frag);
- // unpack upper bound into c_dataBuffer
- const ScanBound& bound = *scan.m_bound[1];
+ // scan direction
+ const unsigned idir = scan.m_descending; // 0, 1
+ const int jdir = 1 - 2 * (int)idir; // 1, -1
+ // unpack end key into c_dataBuffer
+ const ScanBound& bound = *scan.m_bound[1 - idir];
ScanBoundIterator iter;
bound.first(iter);
for (unsigned j = 0; j < bound.getSize(); j++) {
@@ -764,6 +791,11 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
TreeEnt ent;
while (true) {
jam();
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Scan next pos " << pos << " " << node << endl;
+ }
+#endif
if (pos.m_dir == 2) {
// coming up from root ends the scan
jam();
@@ -778,7 +810,7 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
if (pos.m_dir == 4) {
// coming down from parent proceed to left child
jam();
- TupLoc loc = node.getLink(0);
+ TupLoc loc = node.getLink(idir);
if (loc != NullTupLoc) {
jam();
pos.m_loc = loc;
@@ -786,34 +818,42 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
continue;
}
// pretend we came from left child
- pos.m_dir = 0;
+ pos.m_dir = idir;
+ }
+ const unsigned occup = node.getOccup();
+ if (occup == 0) {
+ jam();
+ ndbrequire(fromMaintReq);
+ // move back to parent - see comment in treeRemoveInner
+ pos.m_loc = node.getLink(2);
+ pos.m_dir = node.getSide();
+ continue;
}
- if (pos.m_dir == 0) {
+ if (pos.m_dir == idir) {
// coming up from left child scan current node
jam();
- pos.m_pos = 0;
+ pos.m_pos = idir == 0 ? 0 : occup - 1;
pos.m_match = false;
pos.m_dir = 3;
}
if (pos.m_dir == 3) {
// within node
jam();
- unsigned occup = node.getOccup();
- ndbrequire(occup >= 1);
// advance position
if (! pos.m_match)
pos.m_match = true;
else
- pos.m_pos++;
+ // becomes ZNIL (which is > occup) if 0 and scan descending
+ pos.m_pos += jdir;
if (pos.m_pos < occup) {
jam();
ent = node.getEnt(pos.m_pos);
pos.m_dir = 3; // unchanged
// read and compare all attributes
readKeyAttrs(frag, ent, 0, c_entryKey);
- int ret = cmpScanBound(frag, 1, c_dataBuffer, scan.m_boundCnt[1], c_entryKey);
+ int ret = cmpScanBound(frag, 1 - idir, c_dataBuffer, scan.m_boundCnt[1 - idir], c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (ret < 0) {
+ if (jdir * ret < 0) {
jam();
// hit upper bound of single range scan
pos.m_loc = NullTupLoc;
@@ -830,7 +870,7 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
break;
}
// after node proceed to right child
- TupLoc loc = node.getLink(1);
+ TupLoc loc = node.getLink(1 - idir);
if (loc != NullTupLoc) {
jam();
pos.m_loc = loc;
@@ -838,9 +878,9 @@ Dbtux::scanNext(ScanOpPtr scanPtr)
continue;
}
// pretend we came from right child
- pos.m_dir = 1;
+ pos.m_dir = 1 - idir;
}
- if (pos.m_dir == 1) {
+ if (pos.m_dir == 1 - idir) {
// coming up from right child proceed to parent
jam();
pos.m_loc = node.getLink(2);
@@ -890,7 +930,7 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
Uint32 fragBit = ent.m_fragBit;
Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit];
- Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff);
+ Uint32 fragId = frag.m_fragId | fragBit;
Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
// check for same tuple twice in row
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
index 7057d74c3ad..b0e2a664bfd 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
@@ -253,22 +253,33 @@ Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePo
/*
* Search for scan start position.
*
- * Similar to searchToAdd.
+ * Similar to searchToAdd. The routines differ somewhat depending on
+ * scan direction and are done by separate methods.
*/
void
-Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, 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;
+ if (tree.m_root != NullTupLoc) {
+ if (! descending)
+ searchToScanAscending(frag, boundInfo, boundCount, treePos);
+ else
+ searchToScanDescending(frag, boundInfo, boundCount, treePos);
return;
}
+ // empty tree
+}
+
+void
+Dbtux::searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+{
+ const TreeHead& tree = frag.m_tree;
+ NodeHandle currNode(frag);
+ currNode.m_loc = tree.m_root;
NodeHandle glbNode(frag); // potential g.l.b of final node
NodeHandle bottomNode(frag);
+ // always before entry
+ treePos.m_match = false;
while (true) {
jam();
selectNode(currNode, currNode.m_loc);
@@ -283,6 +294,7 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
}
if (ret < 0) {
+ // bound is left of this node
jam();
const TupLoc loc = currNode.getLink(0);
if (loc != NullTupLoc) {
@@ -300,11 +312,11 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
// 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) {
+ // bound is at or right of this node
jam();
const TupLoc loc = currNode.getLink(1);
if (loc != NullTupLoc) {
@@ -316,7 +328,7 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
continue;
}
} else {
- ndbassert(false);
+ ndbrequire(false);
}
break;
}
@@ -328,20 +340,19 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
ndbrequire(ret != NdbSqlUtil::CmpUnknown);
if (ret < 0) {
- // start scanning from current entry
+ // found first entry satisfying the bound
treePos.m_loc = currNode.m_loc;
treePos.m_pos = j;
- treePos.m_match = false;
treePos.m_dir = 3;
return;
}
}
+ // bound is to right of this node
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;
}
@@ -349,3 +360,90 @@ Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePo
treePos.m_loc = currNode.m_loc;
treePos.m_dir = 1;
}
+
+void
+Dbtux::searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
+{
+ const TreeHead& tree = frag.m_tree;
+ NodeHandle currNode(frag);
+ currNode.m_loc = tree.m_root;
+ NodeHandle glbNode(frag); // potential g.l.b of final node
+ NodeHandle bottomNode(frag);
+ // always before entry
+ treePos.m_match = false;
+ while (true) {
+ jam();
+ selectNode(currNode, currNode.m_loc);
+ int ret;
+ // compare prefix
+ ret = cmpScanBound(frag, 1, 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, 1, boundInfo, boundCount, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ }
+ if (ret < 0) {
+ // bound is left of this node
+ 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 {
+ // empty result set
+ return;
+ }
+ } else if (ret > 0) {
+ // bound is at or right of this node
+ 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 {
+ ndbrequire(false);
+ }
+ break;
+ }
+ 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, 1, boundInfo, boundCount, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ if (ret < 0) {
+ if (j > 0) {
+ // start scanning from previous entry
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = j - 1;
+ treePos.m_dir = 3;
+ return;
+ }
+ // start scanning upwards (pretend we came from left child)
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = 0;
+ treePos.m_dir = 0;
+ return;
+ }
+ }
+ // start scanning this node
+ treePos.m_loc = currNode.m_loc;
+ treePos.m_pos = currNode.getOccup() - 1;
+ treePos.m_dir = 3;
+}
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
index b9e3b593a00..5107a8d8e31 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
@@ -226,6 +226,9 @@ Dbtux::treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos)
// borrow max entry from semi/leaf
Uint32 scanList = RNIL;
nodePopDown(glbNode, glbNode.getOccup() - 1, ent, &scanList);
+ // g.l.b may be empty now
+ // a descending scan may try to enter the empty g.l.b
+ // we prevent this in scanNext
nodePopUp(lubNode, pos, ent, scanList);
if (glbNode.getLink(0) != NullTupLoc) {
jam();
diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt
index 1e6d0a0a329..68120084846 100644
--- a/ndb/src/kernel/blocks/dbtux/Times.txt
+++ b/ndb/src/kernel/blocks/dbtux/Times.txt
@@ -138,6 +138,14 @@ before mc02/c 5 ms 13 ms 126 pct
after mc02/c 5 ms 10 ms 70 pct
mc02/d 178 ms 242 ms 69 pct
-[ prelim preformance fix for max batch size 16 -> 992 ]
+[ prelim performance fix for max batch size 16 -> 992 ]
+
+wl-2066 mc02/c 5 ms 10 ms 87 pct
+before mc02/d 140 ms 237 ms 69 pct
+
+wl-2066 mc02/c 5 ms 10 ms 69 pct
+after mc02/d 150 ms 229 ms 52 pct
+
+[ wl-2066 = remove ACC storage, use TUX test to see effect ]
vim: set et:
diff --git a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
index b94bb8e6d7e..0f45c407d83 100644
--- a/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
+++ b/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
@@ -60,6 +60,7 @@ DbUtil::DbUtil(const Configuration & conf) :
BLOCK_CONSTRUCTOR(DbUtil);
// Add received signals
+ addRecSignal(GSN_READ_CONFIG_REQ, &DbUtil::execREAD_CONFIG_REQ);
addRecSignal(GSN_STTOR, &DbUtil::execSTTOR);
addRecSignal(GSN_NDB_STTOR, &DbUtil::execNDB_STTOR);
addRecSignal(GSN_DUMP_STATE_ORD, &DbUtil::execDUMP_STATE_ORD);
@@ -111,47 +112,6 @@ DbUtil::DbUtil(const Configuration & conf) :
addRecSignal(GSN_UTIL_RELEASE_REQ, &DbUtil::execUTIL_RELEASE_REQ);
addRecSignal(GSN_UTIL_RELEASE_CONF, &DbUtil::execUTIL_RELEASE_CONF);
addRecSignal(GSN_UTIL_RELEASE_REF, &DbUtil::execUTIL_RELEASE_REF);
-
- c_pagePool.setSize(10);
- c_preparePool.setSize(1); // one parallel prepare at a time
- c_preparedOperationPool.setSize(5); // three hardcoded, two for test
- c_operationPool.setSize(64); // 64 parallel operations
- c_transactionPool.setSize(32); // 16 parallel transactions
- c_attrMappingPool.setSize(100);
- c_dataBufPool.setSize(6000); // 6000*11*4 = 264K > 8k+8k*16 = 256k
- {
- SLList<Prepare> tmp(c_preparePool);
- PreparePtr ptr;
- while(tmp.seize(ptr))
- new (ptr.p) Prepare(c_pagePool);
- tmp.release();
- }
- {
- SLList<Operation> tmp(c_operationPool);
- OperationPtr ptr;
- while(tmp.seize(ptr))
- new (ptr.p) Operation(c_dataBufPool, c_dataBufPool, c_dataBufPool);
- tmp.release();
- }
- {
- SLList<PreparedOperation> tmp(c_preparedOperationPool);
- PreparedOperationPtr ptr;
- while(tmp.seize(ptr))
- new (ptr.p) PreparedOperation(c_attrMappingPool,
- c_dataBufPool, c_dataBufPool);
- tmp.release();
- }
- {
- SLList<Transaction> tmp(c_transactionPool);
- TransactionPtr ptr;
- while(tmp.seize(ptr))
- new (ptr.p) Transaction(c_pagePool, c_operationPool);
- tmp.release();
- }
-
- c_lockQueuePool.setSize(5);
- c_lockElementPool.setSize(5);
- c_lockQueues.setSize(8);
}
DbUtil::~DbUtil()
@@ -197,6 +157,68 @@ DbUtil::releaseTransaction(TransactionPtr transPtr){
c_runningTransactions.release(transPtr);
}
+void
+DbUtil::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ c_pagePool.setSize(10);
+ c_preparePool.setSize(1); // one parallel prepare at a time
+ c_preparedOperationPool.setSize(5); // three hardcoded, two for test
+ c_operationPool.setSize(64); // 64 parallel operations
+ c_transactionPool.setSize(32); // 16 parallel transactions
+ c_attrMappingPool.setSize(100);
+ c_dataBufPool.setSize(6000); // 6000*11*4 = 264K > 8k+8k*16 = 256k
+ {
+ SLList<Prepare> tmp(c_preparePool);
+ PreparePtr ptr;
+ while(tmp.seize(ptr))
+ new (ptr.p) Prepare(c_pagePool);
+ tmp.release();
+ }
+ {
+ SLList<Operation> tmp(c_operationPool);
+ OperationPtr ptr;
+ while(tmp.seize(ptr))
+ new (ptr.p) Operation(c_dataBufPool, c_dataBufPool, c_dataBufPool);
+ tmp.release();
+ }
+ {
+ SLList<PreparedOperation> tmp(c_preparedOperationPool);
+ PreparedOperationPtr ptr;
+ while(tmp.seize(ptr))
+ new (ptr.p) PreparedOperation(c_attrMappingPool,
+ c_dataBufPool, c_dataBufPool);
+ tmp.release();
+ }
+ {
+ SLList<Transaction> tmp(c_transactionPool);
+ TransactionPtr ptr;
+ while(tmp.seize(ptr))
+ new (ptr.p) Transaction(c_pagePool, c_operationPool);
+ tmp.release();
+ }
+
+ c_lockQueuePool.setSize(5);
+ c_lockElementPool.setSize(5);
+ c_lockQueues.setSize(8);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
void
DbUtil::execSTTOR(Signal* signal)
{
diff --git a/ndb/src/kernel/blocks/dbutil/DbUtil.hpp b/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
index 5499970fde3..983dd4402a4 100644
--- a/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
+++ b/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
@@ -69,6 +69,7 @@ protected:
/**
* Startup & Misc
*/
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void execNDB_STTOR(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
diff --git a/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp b/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
index ae40a7c4581..7aa5be7a3cb 100644
--- a/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
+++ b/ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp
@@ -173,6 +173,7 @@ private:
// Received signals
void execDUMP_STATE_ORD(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void execTCSEIZECONF(Signal* signal);
void execTCSEIZEREF(Signal* signal);
@@ -225,7 +226,7 @@ private:
CheckNodeGroups::Output checkNodeGroups(Signal*, const NdbNodeBitmask &);
// Generated statement blocks
- void systemErrorLab(Signal* signal);
+ void systemErrorLab(Signal* signal, int line);
void createSystableLab(Signal* signal, unsigned index);
void crSystab7Lab(Signal* signal);
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
index f9414eb8848..08251348b2b 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp
@@ -63,6 +63,7 @@ Ndbcntr::Ndbcntr(const class Configuration & conf):
// Received signals
addRecSignal(GSN_DUMP_STATE_ORD, &Ndbcntr::execDUMP_STATE_ORD);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Ndbcntr::execREAD_CONFIG_REQ);
addRecSignal(GSN_STTOR, &Ndbcntr::execSTTOR);
addRecSignal(GSN_TCSEIZECONF, &Ndbcntr::execTCSEIZECONF);
addRecSignal(GSN_TCSEIZEREF, &Ndbcntr::execTCSEIZEREF);
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index 5a841d6f836..e6bb4d4f14f 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -51,6 +51,10 @@
#include <NdbOut.hpp>
#include <NdbTick.h>
+// used during shutdown for reporting current startphase
+// accessed from Emulator.cpp, NdbShutdown()
+Uint32 g_currentStartPhase;
+
/**
* ALL_BLOCKS Used during start phases and while changing node state
*
@@ -83,6 +87,24 @@ static BlockInfo ALL_BLOCKS[] = {
static const Uint32 ALL_BLOCKS_SZ = sizeof(ALL_BLOCKS)/sizeof(BlockInfo);
+static BlockReference readConfigOrder[ALL_BLOCKS_SZ] = {
+ DBTUP_REF,
+ DBACC_REF,
+ DBTC_REF,
+ DBLQH_REF,
+ DBTUX_REF,
+ DBDICT_REF,
+ DBDIH_REF,
+ NDBFS_REF,
+ NDBCNTR_REF,
+ QMGR_REF,
+ CMVMI_REF,
+ TRIX_REF,
+ BACKUP_REF,
+ DBUTIL_REF,
+ SUMA_REF
+};
+
/*******************************/
/* CONTINUEB */
/*******************************/
@@ -119,7 +141,7 @@ void Ndbcntr::execCONTINUEB(Signal* signal)
else
tmp.appfmt(" %d", to_3);
- progError(__LINE__, ERR_SYSTEM_ERROR, tmp.c_str());
+ progError(__LINE__, NDBD_EXIT_RESTART_TIMEOUT, tmp.c_str());
}
signal->theData[0] = ZSTARTUP;
@@ -132,7 +154,7 @@ void Ndbcntr::execCONTINUEB(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -150,13 +172,6 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal)
jamEntry();
switch (sysErr->errorCode){
- case SystemError::StartInProgressError:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "master start in progress error",
- killingNode);
- break;
-
case SystemError::GCPStopDetected:
BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
@@ -164,20 +179,6 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal)
killingNode);
break;
- case SystemError::ScanfragTimeout:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "a fragment scan timed out and could not be stopped",
- killingNode);
- break;
-
- case SystemError::ScanfragStateError:
- BaseString::snprintf(buf, sizeof(buf),
- "Node %d killed this node because "
- "the state of a fragment scan was out of sync.",
- killingNode);
- break;
-
case SystemError::CopyFragRefError:
BaseString::snprintf(buf, sizeof(buf),
"Node %d killed this node because "
@@ -193,12 +194,31 @@ void Ndbcntr::execSYSTEM_ERROR(Signal* signal)
break;
}
- progError(__LINE__,
- ERR_SYSTEM_ERROR,
- buf);
+ progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR, buf);
return;
}//Ndbcntr::execSYSTEM_ERROR()
+void
+Ndbcntr::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
void Ndbcntr::execSTTOR(Signal* signal)
{
jamEntry();
@@ -322,7 +342,7 @@ void Ndbcntr::execNDB_STTORRY(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
break;
}//switch
@@ -362,7 +382,7 @@ void Ndbcntr::startPhase1Lab(Signal* signal)
void Ndbcntr::execREAD_NODESREF(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Ndbcntr::execREAD_NODESREF()
@@ -373,7 +393,7 @@ void Ndbcntr::execREAD_NODESREF(Signal* signal)
void Ndbcntr::execNDB_STARTREF(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Ndbcntr::execNDB_STARTREF()
@@ -507,6 +527,9 @@ Ndbcntr::execCNTR_START_REF(Signal * signal){
cmasterNodeId = ref->masterNodeId;
sendCntrStartReq(signal);
return;
+ case CntrStartRef::StopInProgress:
+ jam();
+ progError(__LINE__, NDBD_EXIT_RESTART_DURING_SHUTDOWN);
}
ndbrequire(false);
}
@@ -568,6 +591,13 @@ Ndbcntr::execCNTR_START_REP(Signal* signal){
Uint32 nodeId = signal->theData[0];
c_startedNodes.set(nodeId);
c_start.m_starting.clear(nodeId);
+
+ /**
+ * Inform all interested blocks that node has started
+ */
+ for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){
+ sendSignal(ALL_BLOCKS[i].Ref, GSN_NODE_START_REP, signal, 1, JBB);
+ }
if(!c_start.m_starting.isclear()){
jam();
@@ -797,17 +827,9 @@ Ndbcntr::trySystemRestart(Signal* signal){
return false;
}
- if(!allNodes && c_start.m_startPartialTimeout > now){
- jam();
- return false;
- }
-
NodeState::StartType srType = NodeState::ST_SYSTEM_RESTART;
- if(c_start.m_waiting.equal(c_start.m_withoutLog)){
- if(!allNodes){
- jam();
- return false;
- }
+ if(c_start.m_waiting.equal(c_start.m_withoutLog))
+ {
jam();
srType = NodeState::ST_INITIAL_START;
c_start.m_starting = c_start.m_withoutLog; // Used for starting...
@@ -837,10 +859,6 @@ Ndbcntr::trySystemRestart(Signal* signal){
ndbrequire(false); // All nodes -> partitioning, which is not allowed
}
- if(c_start.m_startPartitionedTimeout > now){
- jam();
- return false;
- }
break;
}
@@ -1347,7 +1365,7 @@ void Ndbcntr::execCNTR_WAITREP(Signal* signal)
break;
default:
jam();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
break;
}//switch
}//Ndbcntr::execCNTR_WAITREP()
@@ -1403,22 +1421,19 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
const bool tStartConf = (phase > 2) || (phase == 2 && cndbBlocksCount > 0);
if(tMasterFailed){
- progError(__LINE__,
- ERR_SR_OTHERNODEFAILED,
+ progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED,
"Unhandled node failure during restart");
}
if(tStartConf && tStarting){
// One of other starting nodes has crashed...
- progError(__LINE__,
- ERR_SR_OTHERNODEFAILED,
+ progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED,
"Unhandled node failure of starting node during restart");
}
if(tStartConf && tStarted){
// One of other started nodes has crashed...
- progError(__LINE__,
- ERR_SR_OTHERNODEFAILED,
+ progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED,
"Unhandled node failure of started node during restart");
}
@@ -1453,9 +1468,6 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
sendSignal(BACKUP_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
- sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
if (c_stopRec.stopReq.senderRef)
{
jam();
@@ -1516,7 +1528,7 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
}
}
- signal->theData[0] = EventReport::NODE_FAILREP;
+ signal->theData[0] = NDB_LE_NODE_FAILREP;
signal->theData[2] = 0;
Uint32 nodeId = 0;
@@ -1588,9 +1600,9 @@ void Ndbcntr::execREAD_NODESREQ(Signal* signal)
/*----------------------------------------------------------------------*/
// SENDS APPL_ERROR TO QMGR AND THEN SET A POINTER OUT OF BOUNDS
/*----------------------------------------------------------------------*/
-void Ndbcntr::systemErrorLab(Signal* signal)
+void Ndbcntr::systemErrorLab(Signal* signal, int line)
{
- progError(0, 0); /* BUG INSERTION */
+ progError(line, NDBD_EXIT_NDBREQUIRE); /* BUG INSERTION */
return;
}//Ndbcntr::systemErrorLab()
@@ -1599,10 +1611,9 @@ void Ndbcntr::systemErrorLab(Signal* signal)
/* |-2048| # 1 00000001 | */
/* | : | : | */
/* | -1 | # 1 00000001 | */
-/* | 0 | 0 | */
-/* | 1 | 0 | */
-/* | : | : | */
-/* | 2047| 0 | */
+/* | 1 | 0 | tupleid sequence now created on first use */
+/* | : | : | v */
+/* | 2048| 0 | v */
/*---------------------------------------------------------------------------*/
void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
{
@@ -1637,13 +1648,9 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
ndbassert(column.pos == i);
w.add(DictTabInfo::AttributeName, column.name);
w.add(DictTabInfo::AttributeId, (Uint32)column.pos);
- //w.add(DictTabInfo::AttributeType, DictTabInfo::UnSignedType);
- //w.add(DictTabInfo::AttributeSize, DictTabInfo::a32Bit);
- //w.add(DictTabInfo::AttributeArraySize, 1);
w.add(DictTabInfo::AttributeKeyFlag, (Uint32)column.keyFlag);
//w.add(DictTabInfo::AttributeStorage, (Uint32)DictTabInfo::MainMemory);
w.add(DictTabInfo::AttributeNullableFlag, (Uint32)column.nullable);
- // ext type overrides
w.add(DictTabInfo::AttributeExtType, (Uint32)column.type);
w.add(DictTabInfo::AttributeExtLength, (Uint32)column.length);
w.add(DictTabInfo::AttributeEnd, (Uint32)true);
@@ -1666,7 +1673,7 @@ void Ndbcntr::createSystableLab(Signal* signal, unsigned index)
void Ndbcntr::execCREATE_TABLE_REF(Signal* signal)
{
jamEntry();
- progError(0,0);
+ progError(__LINE__,NDBD_EXIT_NDBREQUIRE, "CREATE_TABLE_REF");
return;
}//Ndbcntr::execDICTTABREF()
@@ -1815,8 +1822,7 @@ void Ndbcntr::crSystab8Lab(Signal* signal)
jam();
ckey = 1;
ctransidPhase = ZFALSE;
- crSystab7Lab(signal);
- return;
+ // skip 2nd loop - tupleid sequence now created on first use
}//if
signal->theData[0] = ctcConnectionP;
signal->theData[1] = reference();
@@ -1867,28 +1873,28 @@ void Ndbcntr::execGETGCICONF(Signal* signal)
void Ndbcntr::execTCKEYREF(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Ndbcntr::execTCKEYREF()
void Ndbcntr::execTCROLLBACKREP(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Ndbcntr::execTCROLLBACKREP()
void Ndbcntr::execTCRELEASEREF(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Ndbcntr::execTCRELEASEREF()
void Ndbcntr::execTCSEIZEREF(Signal* signal)
{
jamEntry();
- systemErrorLab(signal);
+ systemErrorLab(signal, __LINE__);
return;
}//Ndbcntr::execTCSEIZEREF()
@@ -2054,7 +2060,7 @@ Ndbcntr::execRESUME_REQ(Signal* signal){
jamEntry();
- signal->theData[0] = EventReport::SingleUser;
+ signal->theData[0] = NDB_LE_SingleUser;
signal->theData[1] = 2;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -2099,7 +2105,9 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
return;
}
- if(c_stopRec.stopReq.senderRef != 0){
+ if(c_stopRec.stopReq.senderRef != 0 ||
+ (cmasterNodeId == getOwnNodeId() && !c_start.m_starting.isclear()))
+ {
/**
* Requested a system shutdown
*/
@@ -2113,11 +2121,13 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
/**
* Requested a node shutdown
*/
- if(StopReq::getSystemStop(c_stopRec.stopReq.requestInfo))
+ if(c_stopRec.stopReq.senderRef &&
+ StopReq::getSystemStop(c_stopRec.stopReq.requestInfo))
ref->errorCode = StopRef::SystemShutdownInProgress;
else
ref->errorCode = StopRef::NodeShutdownInProgress;
ref->senderData = senderData;
+ ref->masterNodeId = cmasterNodeId;
if (senderRef != RNIL)
sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
@@ -2129,6 +2139,7 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
jam();
ref->errorCode = StopRef::UnsupportedNodeShutdown;
ref->senderData = senderData;
+ ref->masterNodeId = cmasterNodeId;
if (senderRef != RNIL)
sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
return;
@@ -2139,6 +2150,7 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
jam();
ref->errorCode = StopRef::MultiNodeShutdownNotMaster;
ref->senderData = senderData;
+ ref->masterNodeId = cmasterNodeId;
if (senderRef != RNIL)
sendSignal(senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
return;
@@ -2186,13 +2198,13 @@ Ndbcntr::execSTOP_REQ(Signal* signal){
jam();
return;
}
- signal->theData[0] = EventReport::NDBStopStarted;
+ signal->theData[0] = NDB_LE_NDBStopStarted;
signal->theData[1] = StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) ? 1 : 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}
else
{
- signal->theData[0] = EventReport::SingleUser;
+ signal->theData[0] = NDB_LE_SingleUser;
signal->theData[1] = 0;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
}
@@ -2282,6 +2294,7 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
ref->senderData = stopReq.senderData;
ref->errorCode = StopRef::NodeShutdownWouldCauseSystemCrash;
+ ref->masterNodeId = cntr.cmasterNodeId;
const BlockReference bref = stopReq.senderRef;
if (bref != RNIL)
@@ -2295,7 +2308,7 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
cntr.updateNodeState(signal, newState);
}
- signal->theData[0] = EventReport::NDBStopAborted;
+ signal->theData[0] = NDB_LE_NDBStopAborted;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
return false;
@@ -2403,7 +2416,7 @@ void Ndbcntr::execABORT_ALL_CONF(Signal* signal){
c_stopRec.stopReq.senderRef = 0; // the command is done
- signal->theData[0] = EventReport::SingleUser;
+ signal->theData[0] = NDB_LE_SingleUser;
signal->theData[1] = 1;
signal->theData[2] = c_stopRec.stopReq.singleUserApi;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
@@ -2430,6 +2443,7 @@ void Ndbcntr::execABORT_ALL_REF(Signal* signal){
StopRef * const stopRef = (StopRef *)&signal->theData[0];
stopRef->senderData = c_stopRec.stopReq.senderData;
stopRef->errorCode = StopRef::TransactionAbortFailed;
+ stopRef->masterNodeId = cmasterNodeId;
sendSignal(c_stopRec.stopReq.senderRef, GSN_STOP_REF, signal, StopRef::SignalLength, JBB);
}
@@ -2691,7 +2705,7 @@ Ndbcntr::execFSREMOVECONF(Signal* signal){
}
void Ndbcntr::Missra::execSTART_ORD(Signal* signal){
- signal->theData[0] = EventReport::NDBStartStarted;
+ signal->theData[0] = NDB_LE_NDBStartStarted;
signal->theData[1] = NDB_VERSION;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -2709,7 +2723,7 @@ void Ndbcntr::Missra::sendNextREAD_CONFIG_REQ(Signal* signal){
req->senderRef = cntr.reference();
req->noOfParameters = 0;
- const BlockReference ref = ALL_BLOCKS[currentBlockIndex].Ref;
+ const BlockReference ref = readConfigOrder[currentBlockIndex];
#if 0
ndbout_c("sending READ_CONFIG_REQ to %s(ref=%x index=%d)",
@@ -2740,7 +2754,8 @@ void Ndbcntr::Missra::execREAD_CONFIG_CONF(Signal* signal){
const ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtr();
const Uint32 ref = conf->senderRef;
- ndbrequire(refToBlock(ALL_BLOCKS[currentBlockIndex].Ref) == refToBlock(ref));
+ ndbrequire(refToBlock(readConfigOrder[currentBlockIndex])
+ == refToBlock(ref));
currentBlockIndex++;
sendNextREAD_CONFIG_REQ(signal);
@@ -2768,11 +2783,12 @@ void Ndbcntr::Missra::execSTTORRY(Signal* signal){
void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
- for(; currentStartPhase < 255 ; currentStartPhase++){
+ for(; currentStartPhase < 255 ;
+ currentStartPhase++, g_currentStartPhase = currentStartPhase){
jam();
const Uint32 start = currentBlockIndex;
-
+
if (currentStartPhase == ZSTART_PHASE_6)
{
// Ndbd has passed the critical startphases.
@@ -2821,14 +2837,14 @@ void Ndbcntr::Missra::sendNextSTTOR(Signal* signal){
* At least one wanted this start phase, report it
*/
jam();
- signal->theData[0] = EventReport::StartPhaseCompleted;
+ signal->theData[0] = NDB_LE_StartPhaseCompleted;
signal->theData[1] = currentStartPhase;
signal->theData[2] = cntr.ctypeOfStart;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
}
- signal->theData[0] = EventReport::NDBStartCompleted;
+ signal->theData[0] = NDB_LE_NDBStartCompleted;
signal->theData[1] = NDB_VERSION;
cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -2919,7 +2935,8 @@ UpgradeStartup::execCM_APPCHG(SimulatedBlock & block, Signal* signal){
return;
}
}
- block.progError(0,0);
+ block.progError(__LINE__,NDBD_EXIT_NDBREQUIRE,
+ "UpgradeStartup::execCM_APPCHG");
}
void
@@ -2932,7 +2949,9 @@ UpgradeStartup::sendCntrMasterReq(Ndbcntr& cntr, Signal* signal, Uint32 n){
}
if(node == NdbNodeBitmask::NotFound){
- cntr.progError(0,0);
+ cntr.progError(__LINE__,NDBD_EXIT_NDBREQUIRE,
+ "UpgradeStartup::sendCntrMasterReq "
+ "NdbNodeBitmask::NotFound");
}
CntrMasterReq * const cntrMasterReq = (CntrMasterReq*)&signal->theData[0];
@@ -2974,5 +2993,6 @@ UpgradeStartup::execCNTR_MASTER_REPLY(SimulatedBlock & block, Signal* signal){
}
}
}
- block.progError(0,0);
+ block.progError(__LINE__,NDBD_EXIT_NDBREQUIRE,
+ "UpgradeStartup::execCNTR_MASTER_REPLY");
}
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
index c0ffa722f1c..ddf16024017 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp
@@ -18,12 +18,11 @@
#include <my_sys.h>
#include <my_pthread.h>
-#include <Error.hpp>
#include "AsyncFile.hpp"
#include <ErrorHandlingMacros.hpp>
#include <kernel_types.h>
-#include <NdbMem.h>
+#include <ndbd_malloc.hpp>
#include <NdbThread.h>
#include <signaldata/FsOpenReq.hpp>
@@ -96,6 +95,7 @@ AsyncFile::AsyncFile() :
theReportTo(0),
theMemoryChannelPtr(NULL)
{
+ m_current_request= m_last_request= 0;
}
void
@@ -161,7 +161,7 @@ AsyncFile::run()
theStartFlag = true;
// Create write buffer for bigger writes
theWriteBufferSize = WRITEBUFFERSIZE;
- theWriteBuffer = (char *) NdbMem_Allocate(theWriteBufferSize);
+ theWriteBuffer = (char *) ndbd_malloc(theWriteBufferSize);
NdbMutex_Unlock(theStartMutexPtr);
NdbCondition_Signal(theStartConditionPtr);
@@ -177,6 +177,7 @@ AsyncFile::run()
endReq();
return;
}//if
+ m_current_request= request;
switch (request->action) {
case Request:: open:
openReq(request);
@@ -226,6 +227,8 @@ AsyncFile::run()
abort();
break;
}//switch
+ m_last_request= request;
+ m_current_request= 0;
// No need to signal as ndbfs only uses tryRead
theReportTo->writeChannelNoSignal(request);
@@ -509,7 +512,7 @@ AsyncFile::extendfile(Request* request) {
DEBUG(ndbout_c("extendfile: maxOffset=%d, size=%d", maxOffset, maxSize));
// Allocate a buffer and fill it with zeros
- void* pbuf = NdbMem_Allocate(maxSize);
+ void* pbuf = ndbd_malloc(maxSize);
memset(pbuf, 0, maxSize);
for (int p = 0; p <= maxOffset; p = p + maxSize) {
int return_value;
@@ -517,16 +520,18 @@ AsyncFile::extendfile(Request* request) {
p,
SEEK_SET);
if((return_value == -1 ) || (return_value != p)) {
+ ndbd_free(pbuf,maxSize);
return -1;
}
return_value = ::write(theFd,
pbuf,
maxSize);
if ((return_value == -1) || (return_value != maxSize)) {
+ ndbd_free(pbuf,maxSize);
return -1;
}
}
- free(pbuf);
+ ndbd_free(pbuf,maxSize);
DEBUG(ndbout_c("extendfile: \"%s\" OK!", theFileName.c_str()));
return 0;
@@ -876,7 +881,7 @@ AsyncFile::rmrfReq(Request * request, char * path, bool removePath){
void AsyncFile::endReq()
{
// Thread is ended with return
- if (theWriteBuffer) NdbMem_Free(theWriteBuffer);
+ if (theWriteBuffer) ndbd_free(theWriteBuffer, theWriteBufferSize);
}
@@ -1033,3 +1038,60 @@ void printErrorAndFlags(Uint32 used_flags) {
}
#endif
+
+NdbOut&
+operator<<(NdbOut& out, const Request& req)
+{
+ out << "[ Request: file: " << hex << req.file
+ << " userRef: " << hex << req.theUserReference
+ << " userData: " << dec << req.theUserPointer
+ << " theFilePointer: " << req.theFilePointer
+ << " action: ";
+ switch(req.action){
+ case Request::open:
+ out << "open";
+ break;
+ case Request::close:
+ out << "close";
+ break;
+ case Request::closeRemove:
+ out << "closeRemove";
+ break;
+ case Request::read: // Allways leave readv directly after
+ out << "read";
+ break;
+ case Request::readv:
+ out << "readv";
+ break;
+ case Request::write:// Allways leave writev directly after
+ out << "write";
+ break;
+ case Request::writev:
+ out << "writev";
+ break;
+ case Request::writeSync:// Allways leave writevSync directly after
+ out << "writeSync";
+ break;
+ // writeSync because SimblockAsyncFileSystem depends on it
+ case Request::writevSync:
+ out << "writevSync";
+ break;
+ case Request::sync:
+ out << "sync";
+ break;
+ case Request::end:
+ out << "end";
+ break;
+ case Request::append:
+ out << "append";
+ break;
+ case Request::rmrf:
+ out << "rmrf";
+ break;
+ default:
+ out << (Uint32)req.action;
+ break;
+ }
+ out << " ]";
+ return out;
+}
diff --git a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
index 2176c93c5d5..997bf40fe2a 100644
--- a/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp
@@ -160,6 +160,7 @@ public:
Uint32 theTrace;
};
+NdbOut& operator <<(NdbOut&, const Request&);
inline
void
@@ -173,6 +174,7 @@ Request::set(BlockReference userReference,
class AsyncFile
{
+ friend class Ndbfs;
public:
AsyncFile();
~AsyncFile();
@@ -188,6 +190,7 @@ public:
bool isOpen();
Filename theFileName;
+ Request *m_current_request, *m_last_request;
private:
void openReq(Request *request);
diff --git a/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp b/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
index 349cccdbcb4..460ad3f614a 100644
--- a/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp
@@ -68,7 +68,7 @@ class CircularIndex
{
public:
inline CircularIndex( int start= 0,int size=256 );
- operator int ();
+ operator int () const;
CircularIndex& operator ++ ();
friend int full( const CircularIndex& write, const CircularIndex& read );
friend int empty( const CircularIndex& write, const CircularIndex& read );
@@ -77,7 +77,7 @@ private:
int theIndex;
};
-inline CircularIndex::operator int ()
+inline CircularIndex::operator int () const
{
return theIndex;
}
diff --git a/ndb/src/kernel/blocks/ndbfs/Filename.cpp b/ndb/src/kernel/blocks/ndbfs/Filename.cpp
index 15158ec19ef..238390f262c 100644
--- a/ndb/src/kernel/blocks/ndbfs/Filename.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Filename.cpp
@@ -20,7 +20,6 @@
#include "Filename.hpp"
#include "ErrorHandlingMacros.hpp"
-#include "Error.hpp"
#include "RefConvert.hpp"
#include "DebuggerNames.hpp"
@@ -52,7 +51,7 @@ Filename::init(Uint32 nodeid,
DBUG_ENTER("Filename::init");
if (pFileSystemPath == NULL) {
- ERROR_SET(fatal, AFS_ERROR_NOPATH, ""," Filename::init()");
+ ERROR_SET(fatal, NDBD_EXIT_AFS_NOPATH, "","Missing FileSystemPath");
return;
}
@@ -109,7 +108,7 @@ Filename::set(BlockReference blockReference,
{
const char* blockName = getBlockName( refToBlock(blockReference) );
if (blockName == NULL){
- ERROR_SET(ecError, AFS_ERROR_PARAMETER,"","No Block Name");
+ ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","No Block Name");
return;
}
BaseString::snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
@@ -165,7 +164,7 @@ Filename::set(BlockReference blockReference,
const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);
if(diskNo == 0xFF){
- ERROR_SET(ecError, AFS_ERROR_PARAMETER,"","Invalid disk specification");
+ ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Invalid disk specification");
}
BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
@@ -174,10 +173,10 @@ Filename::set(BlockReference blockReference,
}
break;
default:
- ERROR_SET(ecError, AFS_ERROR_PARAMETER,"","Wrong version");
+ ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Wrong version");
}
if (type >= noOfExtensions){
- ERROR_SET(ecError, AFS_ERROR_PARAMETER,"","File Type doesn't exist");
+ ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","File Type doesn't exist");
return;
}
strcat(theName, fileExtension[type]);
diff --git a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
index 6bb9684f3ca..f46cc66fe16 100644
--- a/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp
@@ -70,7 +70,6 @@
#else
#include "ErrorHandlingMacros.hpp"
-#include "Error.hpp"
#include "CircularIndex.hpp"
#include "NdbMutex.h"
#include "NdbCondition.h"
@@ -97,8 +96,20 @@ private:
NdbMutex* theMutexPtr;
NdbCondition* theConditionPtr;
+ template<class U>
+ friend NdbOut& operator<<(NdbOut& out, const MemoryChannel<U> & chn);
};
+template <class T>
+NdbOut& operator<<(NdbOut& out, const MemoryChannel<T> & chn)
+{
+ NdbMutex_Lock(chn.theMutexPtr);
+ out << "[ theSize: " << chn.theSize
+ << " theReadIndex: " << (int)chn.theReadIndex
+ << " theWriteIndex: " << (int)chn.theWriteIndex << " ]";
+ NdbMutex_Unlock(chn.theMutexPtr);
+ return out;
+}
template <class T> MemoryChannel<T>::MemoryChannel( int size):
theSize(size),
diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
index 6f848d7fe16..5049c726315 100644
--- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp
@@ -19,7 +19,6 @@
#include "Ndbfs.hpp"
#include "AsyncFile.hpp"
#include "Filename.hpp"
-#include "Error.hpp"
#include <signaldata/FsOpenReq.hpp>
#include <signaldata/FsCloseReq.hpp>
@@ -57,26 +56,10 @@ Ndbfs::Ndbfs(const Configuration & conf) :
theLastId(0),
m_maxOpenedFiles(0)
{
- theFileSystemPath = conf.fileSystemPath();
- theBackupFilePath = conf.backupFilePath();
-
- theRequestPool = new Pool<Request>;
-
- const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- m_maxFiles = 40;
- ndb_mgm_get_int_parameter(p, CFG_DB_MAX_OPEN_FILES, &m_maxFiles);
-
- // Create idle AsyncFiles
- Uint32 noIdleFiles = m_maxFiles > 27 ? 27 : m_maxFiles ;
- for (Uint32 i = 0; i < noIdleFiles; i++){
- theIdleFiles.push_back(createAsyncFile());
- }
-
BLOCK_CONSTRUCTOR(Ndbfs);
// Set received signals
+ addRecSignal(GSN_READ_CONFIG_REQ, &Ndbfs::execREAD_CONFIG_REQ);
addRecSignal(GSN_DUMP_STATE_ORD, &Ndbfs::execDUMP_STATE_ORD);
addRecSignal(GSN_STTOR, &Ndbfs::execSTTOR);
addRecSignal(GSN_FSOPENREQ, &Ndbfs::execFSOPENREQ);
@@ -88,6 +71,8 @@ Ndbfs::Ndbfs(const Configuration & conf) :
addRecSignal(GSN_FSAPPENDREQ, &Ndbfs::execFSAPPENDREQ);
addRecSignal(GSN_FSREMOVEREQ, &Ndbfs::execFSREMOVEREQ);
// Set send signals
+
+ theRequestPool = 0;
}
Ndbfs::~Ndbfs()
@@ -102,7 +87,41 @@ Ndbfs::~Ndbfs()
}//for
theFiles.clear();
- delete theRequestPool;
+ if (theRequestPool)
+ delete theRequestPool;
+}
+
+void
+Ndbfs::execREAD_CONFIG_REQ(Signal* signal)
+{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ theFileSystemPath = theConfiguration.fileSystemPath();
+ theBackupFilePath = theConfiguration.backupFilePath();
+
+ theRequestPool = new Pool<Request>;
+
+ m_maxFiles = 40;
+ ndb_mgm_get_int_parameter(p, CFG_DB_MAX_OPEN_FILES, &m_maxFiles);
+
+ // Create idle AsyncFiles
+ Uint32 noIdleFiles = m_maxFiles > 27 ? 27 : m_maxFiles ;
+ for (Uint32 i = 0; i < noIdleFiles; i++){
+ theIdleFiles.push_back(createAsyncFile());
+ }
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
}
/* Received a restart signal.
@@ -557,7 +576,7 @@ Ndbfs::createAsyncFile(){
AsyncFile* file = theFiles[i];
ndbout_c("%2d (0x%x): %s", i, file, file->isOpen()?"OPEN":"CLOSED");
}
- ERROR_SET(fatal, AFS_ERROR_MAXOPEN,""," Ndbfs::createAsyncFile");
+ ERROR_SET(fatal, NDBD_EXIT_AFS_MAXOPEN,""," Ndbfs::createAsyncFile");
}
AsyncFile* file = new AsyncFile;
@@ -1006,6 +1025,30 @@ Ndbfs::execDUMP_STATE_ORD(Signal* signal)
}
return;
}
+
+ if(signal->theData[0] == 404)
+ {
+ ndbrequire(signal->getLength() == 2);
+ Uint32 file= signal->theData[1];
+ AsyncFile* openFile = theOpenFiles.find(file);
+ ndbrequire(openFile);
+ ndbout_c("File: %s %p", openFile->theFileName.c_str(), openFile);
+ Request* curr = openFile->m_current_request;
+ Request* last = openFile->m_last_request;
+ if(curr)
+ ndbout << "Current request: " << *curr << endl;
+ if(last)
+ ndbout << "Last request: " << *last << endl;
+
+ ndbout << "theReportTo " << *openFile->theReportTo << endl;
+ ndbout << "theMemoryChannelPtr" << *openFile->theMemoryChannelPtr << endl;
+
+ ndbout << "All files: " << endl;
+ for (unsigned i = 0; i < theFiles.size(); i++){
+ AsyncFile* file = theFiles[i];
+ ndbout_c("%2d (0x%x): %s", i,file, file->isOpen()?"OPEN":"CLOSED");
+ }
+ }
}//Ndbfs::execDUMP_STATE_ORD()
@@ -1016,3 +1059,4 @@ template class Vector<AsyncFile*>;
template class Vector<OpenFiles::OpenFileItem>;
template class MemoryChannel<Request>;
template class Pool<Request>;
+template NdbOut& operator<<(NdbOut&, const MemoryChannel<Request>&);
diff --git a/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp b/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
index c5aaa4e5c49..17ce8fbd8aa 100644
--- a/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp
@@ -41,6 +41,7 @@ protected:
BLOCK_DEFINES(Ndbfs);
// The signal processing functions
+ void execREAD_CONFIG_REQ(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
void execFSOPENREQ(Signal* signal);
void execFSCLOSEREQ(Signal* signal);
@@ -103,6 +104,7 @@ protected:
BLOCK_DEFINES(VoidFs);
// The signal processing functions
+ void execREAD_CONFIG_REQ(Signal* signal);
void execDUMP_STATE_ORD(Signal* signal);
void execFSOPENREQ(Signal* signal);
void execFSCLOSEREQ(Signal* signal);
diff --git a/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp b/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
index 0fee687f1bc..eacda6ec77d 100644
--- a/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
+++ b/ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp
@@ -88,7 +88,7 @@ inline bool OpenFiles::insert(AsyncFile* file, Uint16 id){
names.assfmt("open: >%s< existing: >%s<",
file->theFileName.c_str(),
m_files[i].m_file->theFileName.c_str());
- ERROR_SET(fatal, AFS_ERROR_ALLREADY_OPEN, names.c_str(),
+ ERROR_SET(fatal, NDBD_EXIT_AFS_ALREADY_OPEN, names.c_str(),
"OpenFiles::insert()");
}
}
diff --git a/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp b/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp
index d093089acfc..5a03d8bb1a0 100644
--- a/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp
+++ b/ndb/src/kernel/blocks/ndbfs/VoidFs.cpp
@@ -20,7 +20,6 @@
#include "Ndbfs.hpp"
#include "AsyncFile.hpp"
#include "Filename.hpp"
-#include "Error.hpp"
#include <signaldata/FsOpenReq.hpp>
#include <signaldata/FsCloseReq.hpp>
@@ -45,6 +44,7 @@ VoidFs::VoidFs(const Configuration & conf) :
BLOCK_CONSTRUCTOR(VoidFs);
// Set received signals
+ addRecSignal(GSN_READ_CONFIG_REQ, &VoidFs::execREAD_CONFIG_REQ);
addRecSignal(GSN_DUMP_STATE_ORD, &VoidFs::execDUMP_STATE_ORD);
addRecSignal(GSN_STTOR, &VoidFs::execSTTOR);
addRecSignal(GSN_FSOPENREQ, &VoidFs::execFSOPENREQ);
@@ -61,6 +61,21 @@ VoidFs::~VoidFs()
{
}
+void
+VoidFs::execREAD_CONFIG_REQ(Signal* signal)
+{
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
void
VoidFs::execSTTOR(Signal* signal)
{
diff --git a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
index 02be002cae0..e728ea81a7d 100644
--- a/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
+++ b/ndb/src/kernel/blocks/qmgr/Qmgr.hpp
@@ -50,6 +50,7 @@
#define ZAPI_HB_HANDLING 3
#define ZTIMER_HANDLING 4
#define ZARBIT_HANDLING 5
+#define ZSTART_FAILURE_LIMIT 6
/* Error Codes ------------------------------*/
#define ZERRTOOMANY 1101
@@ -113,8 +114,19 @@ public:
Uint32 m_gsn;
SignalCounter m_nodes;
- } c_start;
+ Uint32 m_latest_gci;
+
+ Uint32 m_start_type;
+ NdbNodeBitmask m_skip_nodes;
+ NdbNodeBitmask m_starting_nodes;
+ NdbNodeBitmask m_starting_nodes_w_log;
+ Uint16 m_president_candidate;
+ Uint32 m_president_candidate_gci;
+ Uint16 m_regReqReqSent;
+ Uint16 m_regReqReqRecv;
+ } c_start;
+
NdbNodeBitmask c_definedNodes; // DB nodes in config
NdbNodeBitmask c_clusterNodes; // DB nodes in cluster
NodeBitmask c_connectedNodes; // All kinds of connected nodes
@@ -125,15 +137,14 @@ public:
* i.e. nodes that connect to use, when we already have elected president
*/
NdbNodeBitmask c_readnodes_nodes;
-
+
Uint32 c_maxDynamicId;
// Records
struct NodeRec {
UintR ndynamicId;
Phase phase;
- UintR alarmCount;
-
+
QmgrState sendPrepFailReqStatus;
QmgrState sendCommitFailReqStatus;
QmgrState sendPresToStatus;
@@ -225,6 +236,7 @@ private:
void execDUMP_STATE_ORD(Signal* signal);
void execCONNECT_REP(Signal* signal);
void execNDB_FAILCONF(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void execCM_INFOCONF(Signal* signal);
void execCLOSE_COMCONF(Signal* signal);
@@ -236,6 +248,9 @@ private:
void execREAD_NODESREF(Signal* signal);
void execREAD_NODESCONF(Signal* signal);
+ void execDIH_RESTARTREF(Signal* signal);
+ void execDIH_RESTARTCONF(Signal* signal);
+
void execAPI_VERSION_REQ(Signal* signal);
void execAPI_BROADCAST_REP(Signal* signal);
@@ -252,6 +267,7 @@ private:
// Statement blocks
void check_readnodes_reply(Signal* signal, Uint32 nodeId, Uint32 gsn);
+ Uint32 check_startup(Signal* signal);
void node_failed(Signal* signal, Uint16 aFailedNode);
void checkStartInterface(Signal* signal);
@@ -324,7 +340,7 @@ private:
void stateArbitChoose(Signal* signal);
void stateArbitCrash(Signal* signal);
void computeArbitNdbMask(NodeBitmask& aMask);
- void reportArbitEvent(Signal* signal, EventReport::EventType type);
+ void reportArbitEvent(Signal* signal, Ndb_logevent_type type);
// Initialisation
void initData();
@@ -374,12 +390,12 @@ private:
/* Status flags ----------------------------------*/
Uint32 c_restartPartialTimeout;
+ Uint32 c_restartPartionedTimeout;
+ Uint32 c_restartFailureTimeout;
+ Uint64 c_start_election_time;
Uint16 creadyDistCom;
- Uint16 c_regReqReqSent;
- Uint16 c_regReqReqRecv;
- Uint64 c_stopElectionTime;
- Uint16 cpresidentCandidate;
+
Uint16 cdelayRegreq;
Uint16 cpresidentAlive;
Uint16 cnoFailedNodes;
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp b/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
index a8fe30d8cfa..f14cbd48695 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrInit.cpp
@@ -35,6 +35,7 @@ void Qmgr::initData()
Uint32 hbDBAPI = 500;
setHbApiDelay(hbDBAPI);
+ c_connectedNodes.set(getOwnNodeId());
c_stopReq.senderRef = 0;
}//Qmgr::initData()
@@ -74,6 +75,7 @@ Qmgr::Qmgr(const class Configuration & conf)
// Received signals
addRecSignal(GSN_CONNECT_REP, &Qmgr::execCONNECT_REP);
addRecSignal(GSN_NDB_FAILCONF, &Qmgr::execNDB_FAILCONF);
+ addRecSignal(GSN_READ_CONFIG_REQ, &Qmgr::execREAD_CONFIG_REQ);
addRecSignal(GSN_STTOR, &Qmgr::execSTTOR);
addRecSignal(GSN_CLOSE_COMCONF, &Qmgr::execCLOSE_COMCONF);
addRecSignal(GSN_API_REGREQ, &Qmgr::execAPI_REGREQ);
@@ -96,6 +98,9 @@ Qmgr::Qmgr(const class Configuration & conf)
addRecSignal(GSN_READ_NODESREF, &Qmgr::execREAD_NODESREF);
addRecSignal(GSN_READ_NODESCONF, &Qmgr::execREAD_NODESCONF);
+
+ addRecSignal(GSN_DIH_RESTARTREF, &Qmgr::execDIH_RESTARTREF);
+ addRecSignal(GSN_DIH_RESTARTCONF, &Qmgr::execDIH_RESTARTCONF);
initData();
}//Qmgr::Qmgr()
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 8b7caadfeb9..cc981f37987 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -94,7 +94,7 @@ void Qmgr::execCM_HEARTBEAT(Signal* signal)
jamEntry();
hbNodePtr.i = signal->theData[0];
ptrCheckGuard(hbNodePtr, MAX_NDB_NODES, nodeRec);
- hbNodePtr.p->alarmCount = 0;
+ setNodeInfo(hbNodePtr.i).m_heartbeat_cnt= 0;
return;
}//Qmgr::execCM_HEARTBEAT()
@@ -146,6 +146,30 @@ void Qmgr::execCONTINUEB(Signal* signal)
runArbitThread(signal);
return;
break;
+ case ZSTART_FAILURE_LIMIT:{
+ if (cpresident != ZNIL)
+ {
+ jam();
+ return;
+ }
+ Uint64 now = NdbTick_CurrentMillisecond();
+ if (now > (c_start_election_time + c_restartFailureTimeout))
+ {
+ jam();
+ BaseString tmp;
+ tmp.append("Shutting down node as total restart time exceeds "
+ " StartFailureTimeout as set in config file ");
+ if(c_restartFailureTimeout == ~0)
+ tmp.append(" 0 (inifinite)");
+ else
+ tmp.appfmt(" %d", c_restartFailureTimeout);
+
+ progError(__LINE__, NDBD_EXIT_SYSTEM_ERROR, tmp.c_str());
+ }
+ signal->theData[0] = ZSTART_FAILURE_LIMIT;
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000, 1);
+ return;
+ }
default:
jam();
// ZCOULD_NOT_OCCUR_ERROR;
@@ -193,6 +217,27 @@ void Qmgr::execPRES_TOREQ(Signal* signal)
return;
}//Qmgr::execPRES_TOREQ()
+void
+Qmgr::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
+}
+
/*
4.2 ADD NODE MODULE*/
/*##########################################################################*/
@@ -252,14 +297,28 @@ void Qmgr::startphase1(Signal* signal)
nodePtr.p->phase = ZSTARTING;
nodePtr.p->blockRef = reference();
c_connectedNodes.set(nodePtr.i);
+
+ signal->theData[0] = reference();
+ sendSignal(DBDIH_REF, GSN_DIH_RESTARTREQ, signal, 1, JBB);
+ return;
+}
- signal->theData[0] = 0; // no answer
- signal->theData[1] = 0; // no id
- signal->theData[2] = NodeInfo::DB;
- sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 3, JBB);
+void
+Qmgr::execDIH_RESTARTREF(Signal*signal)
+{
+ jamEntry();
+ c_start.m_latest_gci = 0;
+ execCM_INFOCONF(signal);
+}
+
+void
+Qmgr::execDIH_RESTARTCONF(Signal*signal)
+{
+ jamEntry();
+
+ c_start.m_latest_gci = signal->theData[1];
execCM_INFOCONF(signal);
- return;
}
void Qmgr::setHbDelay(UintR aHbDelay)
@@ -379,6 +438,7 @@ void Qmgr::execCONNECT_REP(Signal* signal)
void
Qmgr::execREAD_NODESCONF(Signal* signal)
{
+ jamEntry();
check_readnodes_reply(signal,
refToNode(signal->getSendersBlockRef()),
GSN_READ_NODESCONF);
@@ -387,6 +447,7 @@ Qmgr::execREAD_NODESCONF(Signal* signal)
void
Qmgr::execREAD_NODESREF(Signal* signal)
{
+ jamEntry();
check_readnodes_reply(signal,
refToNode(signal->getSendersBlockRef()),
GSN_READ_NODESREF);
@@ -397,25 +458,44 @@ Qmgr::execREAD_NODESREF(Signal* signal)
/*******************************/
void Qmgr::execCM_INFOCONF(Signal* signal)
{
+ /**
+ * Open communcation to all DB nodes
+ */
+ signal->theData[0] = 0; // no answer
+ signal->theData[1] = 0; // no id
+ signal->theData[2] = NodeInfo::DB;
+ sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 3, JBB);
+
cpresident = ZNIL;
- cpresidentCandidate = getOwnNodeId();
cpresidentAlive = ZFALSE;
- c_stopElectionTime = NdbTick_CurrentMillisecond();
- c_stopElectionTime += c_restartPartialTimeout;
+ c_start_election_time = NdbTick_CurrentMillisecond();
+
+ signal->theData[0] = ZSTART_FAILURE_LIMIT;
+ sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3000, 1);
+
cmInfoconf010Lab(signal);
return;
}//Qmgr::execCM_INFOCONF()
+Uint32 g_start_type = 0;
+NdbNodeBitmask g_nowait_nodes; // Set by clo
+
void Qmgr::cmInfoconf010Lab(Signal* signal)
{
c_start.m_startKey = 0;
c_start.m_startNode = getOwnNodeId();
c_start.m_nodes.clearWaitingFor();
c_start.m_gsn = GSN_CM_REGREQ;
+ c_start.m_starting_nodes.clear();
+ c_start.m_starting_nodes_w_log.clear();
+ c_start.m_regReqReqSent = 0;
+ c_start.m_regReqReqRecv = 0;
+ c_start.m_skip_nodes = g_nowait_nodes;
+ c_start.m_skip_nodes.bitAND(c_definedNodes);
+ c_start.m_start_type = g_start_type;
NodeRecPtr nodePtr;
- c_regReqReqSent = c_regReqReqRecv = 0;
cnoOfNodes = 0;
for (nodePtr.i = 1; nodePtr.i < MAX_NDB_NODES; nodePtr.i++) {
jam();
@@ -450,14 +530,18 @@ void Qmgr::cmInfoconf010Lab(Signal* signal)
void
Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){
- c_regReqReqSent++;
- CmRegReq * const cmRegReq = (CmRegReq *)&signal->theData[0];
- cmRegReq->blockRef = reference();
- cmRegReq->nodeId = getOwnNodeId();
- cmRegReq->version = NDB_VERSION;
+ CmRegReq * req = (CmRegReq *)&signal->theData[0];
+ req->blockRef = reference();
+ req->nodeId = getOwnNodeId();
+ req->version = NDB_VERSION;
+ req->latest_gci = c_start.m_latest_gci;
+ req->start_type = c_start.m_start_type;
+ c_start.m_skip_nodes.copyto(NdbNodeBitmask::Size, req->skip_nodes);
const Uint32 ref = calcQmgrBlockRef(nodeId);
sendSignal(ref, GSN_CM_REGREQ, signal, CmRegReq::SignalLength, JBB);
DEBUG_START(GSN_CM_REGREQ, nodeId, "");
+
+ c_start.m_regReqReqSent++;
}
/*
@@ -497,6 +581,18 @@ Qmgr::sendCmRegReq(Signal * signal, Uint32 nodeId){
/*******************************/
/* CM_REGREQ */
/*******************************/
+static
+int
+check_start_type(Uint32 starting, Uint32 own)
+{
+ if (starting == (1 << NodeState::ST_INITIAL_START) &&
+ ((own & (1 << NodeState::ST_INITIAL_START)) == 0))
+ {
+ return 1;
+ }
+ return 0;
+}
+
void Qmgr::execCM_REGREQ(Signal* signal)
{
DEBUG_START3(signal, "");
@@ -508,6 +604,17 @@ void Qmgr::execCM_REGREQ(Signal* signal)
const BlockReference Tblockref = cmRegReq->blockRef;
const Uint32 startingVersion = cmRegReq->version;
addNodePtr.i = cmRegReq->nodeId;
+ Uint32 gci = 1;
+ Uint32 start_type = ~0;
+ NdbNodeBitmask skip_nodes;
+
+ if (signal->getLength() == CmRegReq::SignalLength)
+ {
+ jam();
+ gci = cmRegReq->latest_gci;
+ start_type = cmRegReq->start_type;
+ skip_nodes.assign(NdbNodeBitmask::Size, cmRegReq->skip_nodes);
+ }
if (creadyDistCom == ZFALSE) {
jam();
@@ -521,11 +628,19 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}
- ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
-
- if (cpresident != getOwnNodeId()){
+ if (check_start_type(start_type, c_start.m_start_type))
+ {
+ jam();
+ sendCmRegrefLab(signal, Tblockref, CmRegRef::ZINCOMPATIBLE_START_TYPE);
+ return;
+ }
+
+ if (cpresident != getOwnNodeId())
+ {
jam();
- if (cpresident == ZNIL) {
+
+ if (cpresident == ZNIL)
+ {
/***
* We don't know the president.
* If the node to be added has lower node id
@@ -533,13 +648,18 @@ void Qmgr::execCM_REGREQ(Signal* signal)
* candidate
*/
jam();
- if (addNodePtr.i < cpresidentCandidate) {
+ if (gci > c_start.m_president_candidate_gci ||
+ (gci == c_start.m_president_candidate_gci &&
+ addNodePtr.i < c_start.m_president_candidate))
+ {
jam();
- cpresidentCandidate = addNodePtr.i;
- }//if
+ c_start.m_president_candidate = addNodePtr.i;
+ c_start.m_president_candidate_gci = gci;
+ }
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZELECTION);
return;
- }
+ }
+
/**
* We are not the president.
* We know the president.
@@ -549,7 +669,8 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}//if
- if (c_start.m_startNode != 0){
+ if (c_start.m_startNode != 0)
+ {
jam();
/**
* President busy by adding another node
@@ -558,7 +679,8 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}//if
- if (ctoStatus == Q_ACTIVE) {
+ if (ctoStatus == Q_ACTIVE)
+ {
jam();
/**
* Active taking over as president
@@ -567,7 +689,8 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}//if
- if (getNodeInfo(addNodePtr.i).m_type != NodeInfo::DB) {
+ if (getNodeInfo(addNodePtr.i).m_type != NodeInfo::DB)
+ {
jam();
/**
* The new node is not in config file
@@ -576,13 +699,15 @@ void Qmgr::execCM_REGREQ(Signal* signal)
return;
}
+ ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
Phase phase = addNodePtr.p->phase;
- if (phase != ZINIT){
+ if (phase != ZINIT)
+ {
jam();
DEBUG("phase = " << phase);
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_DEAD);
return;
- }//if
+ }
jam();
/**
@@ -654,7 +779,12 @@ void Qmgr::sendCmRegrefLab(Signal* signal, BlockReference TBRef,
ref->blockRef = reference();
ref->nodeId = getOwnNodeId();
ref->errorCode = Terror;
- ref->presidentCandidate = (cpresident == ZNIL ? cpresidentCandidate : cpresident);
+ ref->presidentCandidate =
+ (cpresident == ZNIL ? c_start.m_president_candidate : cpresident);
+ ref->candidate_latest_gci = c_start.m_president_candidate_gci;
+ ref->latest_gci = c_start.m_latest_gci;
+ ref->start_type = c_start.m_start_type;
+ c_start.m_skip_nodes.copyto(NdbNodeBitmask::Size, ref->skip_nodes);
sendSignal(TBRef, GSN_CM_REGREF, signal,
CmRegRef::SignalLength, JBB);
DEBUG_START(GSN_CM_REGREF, refToNode(TBRef), "");
@@ -713,7 +843,7 @@ void Qmgr::execCM_REGCONF(Signal* signal)
// Send this as an EVENT REPORT to inform about hearing about
// other NDB node proclaiming to be president.
/*--------------------------------------------------------------*/
- signal->theData[0] = EventReport::CM_REGCONF;
+ signal->theData[0] = NDB_LE_CM_REGCONF;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = cpresident;
signal->theData[3] = TdynamicId;
@@ -779,9 +909,9 @@ retry:
char buf[255];
BaseString::snprintf(buf, sizeof(buf),
- "Partitioned cluster! check StartPartialTimeout, "
- " node %d thinks %d is president, "
- " I think president is: %d",
+ "check StartPartialTimeout, "
+ "node %d thinks %d is president, "
+ "I think president is: %d",
nodeId, president, cpresident);
ndbout_c(buf);
@@ -813,7 +943,7 @@ retry:
CRASH_INSERTION(932);
progError(__LINE__,
- ERR_ARBIT_SHUTDOWN,
+ NDBD_EXIT_PARTITIONED_SHUTDOWN,
buf);
ndbrequire(false);
@@ -848,28 +978,105 @@ Qmgr::sendCmNodeInfoReq(Signal* signal, Uint32 nodeId, const NodeRec * self){
/*******************************/
/* CM_REGREF */
/*******************************/
+static
+const char *
+get_start_type_string(Uint32 st)
+{
+ static char buf[256];
+
+ if (st == 0)
+ {
+ return "<ANY>";
+ }
+ else
+ {
+ buf[0] = 0;
+ for(Uint32 i = 0; i<NodeState::ST_ILLEGAL_TYPE; i++)
+ {
+ if (st & (1 << i))
+ {
+ if (buf[0])
+ strcat(buf, "/");
+ switch(i){
+ case NodeState::ST_INITIAL_START:
+ strcat(buf, "inital start");
+ break;
+ case NodeState::ST_SYSTEM_RESTART:
+ strcat(buf, "system restart");
+ break;
+ case NodeState::ST_NODE_RESTART:
+ strcat(buf, "node restart");
+ break;
+ case NodeState::ST_INITIAL_NODE_RESTART:
+ strcat(buf, "initial node restart");
+ break;
+ }
+ }
+ }
+ return buf;
+ }
+}
+
void Qmgr::execCM_REGREF(Signal* signal)
{
jamEntry();
- UintR TaddNodeno = signal->theData[1];
- UintR TrefuseReason = signal->theData[2];
- Uint32 candidate = signal->theData[3];
+ CmRegRef* ref = (CmRegRef*)signal->getDataPtr();
+ UintR TaddNodeno = ref->nodeId;
+ UintR TrefuseReason = ref->errorCode;
+ Uint32 candidate = ref->presidentCandidate;
+ Uint32 node_gci = 1;
+ Uint32 candidate_gci = 1;
+ Uint32 start_type = ~0;
+ NdbNodeBitmask skip_nodes;
DEBUG_START3(signal, TrefuseReason);
- c_regReqReqRecv++;
+ if (signal->getLength() == CmRegRef::SignalLength)
+ {
+ jam();
+ node_gci = ref->latest_gci;
+ candidate_gci = ref->candidate_latest_gci;
+ start_type = ref->start_type;
+ skip_nodes.assign(NdbNodeBitmask::Size, ref->skip_nodes);
+ }
+
+ c_start.m_regReqReqRecv++;
// Ignore block reference in data[0]
- if(candidate != cpresidentCandidate){
+ if(candidate != c_start.m_president_candidate)
+ {
jam();
- c_regReqReqRecv = ~0;
+ c_start.m_regReqReqRecv = ~0;
}
-
+
+ c_start.m_starting_nodes.set(TaddNodeno);
+ if (node_gci)
+ {
+ jam();
+ c_start.m_starting_nodes_w_log.set(TaddNodeno);
+ }
+
+ skip_nodes.bitAND(c_definedNodes);
+ c_start.m_skip_nodes.bitOR(skip_nodes);
+
+ char buf[100];
switch (TrefuseReason) {
case CmRegRef::ZINCOMPATIBLE_VERSION:
jam();
- systemErrorLab(signal, __LINE__, "incompatible version, connection refused by running ndb node");
+ systemErrorLab(signal, __LINE__,
+ "incompatible version, "
+ "connection refused by running ndb node");
+ case CmRegRef::ZINCOMPATIBLE_START_TYPE:
+ jam();
+ BaseString::snprintf(buf, sizeof(buf),
+ "incompatible start type detected: node %d"
+ " reports %s(%d) my start type: %s(%d)",
+ TaddNodeno,
+ get_start_type_string(start_type), start_type,
+ get_start_type_string(c_start.m_start_type),
+ c_start.m_start_type);
+ progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf);
break;
case CmRegRef::ZBUSY:
case CmRegRef::ZBUSY_TO_PRES:
@@ -880,22 +1087,26 @@ void Qmgr::execCM_REGREF(Signal* signal)
break;
case CmRegRef::ZNOT_IN_CFG:
jam();
- progError(__LINE__, ERR_NODE_NOT_IN_CONFIG);
+ progError(__LINE__, NDBD_EXIT_NODE_NOT_IN_CONFIG);
break;
case CmRegRef::ZNOT_DEAD:
jam();
- progError(__LINE__, ERR_NODE_NOT_DEAD);
+ progError(__LINE__, NDBD_EXIT_NODE_NOT_DEAD);
break;
case CmRegRef::ZELECTION:
jam();
- if (cpresidentCandidate > TaddNodeno) {
+ if (candidate_gci > c_start.m_president_candidate_gci ||
+ (candidate_gci == c_start.m_president_candidate_gci &&
+ candidate < c_start.m_president_candidate))
+ {
jam();
//----------------------------------------
/* We may already have a candidate */
/* choose the lowest nodeno */
//----------------------------------------
signal->theData[3] = 2;
- cpresidentCandidate = TaddNodeno;
+ c_start.m_president_candidate = candidate;
+ c_start.m_president_candidate_gci = candidate_gci;
} else {
signal->theData[3] = 4;
}//if
@@ -915,7 +1126,7 @@ void Qmgr::execCM_REGREF(Signal* signal)
// Send this as an EVENT REPORT to inform about hearing about
// other NDB node proclaiming not to be president.
/*--------------------------------------------------------------*/
- signal->theData[0] = EventReport::CM_REGREF;
+ signal->theData[0] = NDB_LE_CM_REGREF;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = TaddNodeno;
//-----------------------------------------
@@ -923,32 +1134,34 @@ void Qmgr::execCM_REGREF(Signal* signal)
//-----------------------------------------
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
- if(cpresidentAlive == ZTRUE){
+ if(cpresidentAlive == ZTRUE)
+ {
jam();
- DEBUG("");
+ DEBUG("cpresidentAlive");
return;
}
- if(c_regReqReqSent != c_regReqReqRecv){
+ if(c_start.m_regReqReqSent != c_start.m_regReqReqRecv)
+ {
jam();
- DEBUG( c_regReqReqSent << " != " << c_regReqReqRecv);
+ DEBUG(c_start.m_regReqReqSent << " != " << c_start.m_regReqReqRecv);
return;
}
- if(cpresidentCandidate != getOwnNodeId()){
+ if(c_start.m_president_candidate != getOwnNodeId())
+ {
jam();
- DEBUG("");
+ DEBUG("i'm not the candidate");
return;
}
-
+
/**
- * All configured nodes has agreed
+ * All connected nodes has agreed
*/
- Uint64 now = NdbTick_CurrentMillisecond();
- if((c_regReqReqRecv == cnoOfNodes) || now > c_stopElectionTime){
+ if(check_startup(signal))
+ {
jam();
electionWon(signal);
- sendSttorryLab(signal);
/**
* Start timer handling
@@ -960,6 +1173,191 @@ void Qmgr::execCM_REGREF(Signal* signal)
return;
}//Qmgr::execCM_REGREF()
+Uint32
+Qmgr::check_startup(Signal* signal)
+{
+ Uint64 now = NdbTick_CurrentMillisecond();
+ Uint64 partial_timeout = c_start_election_time + c_restartPartialTimeout;
+ Uint64 partitioned_timeout = partial_timeout + c_restartPartionedTimeout;
+
+ /**
+ * First see if we should wait more...
+ */
+ NdbNodeBitmask tmp;
+ tmp.bitOR(c_start.m_skip_nodes);
+ tmp.bitOR(c_start.m_starting_nodes);
+
+ NdbNodeBitmask wait;
+ wait.assign(c_definedNodes);
+ wait.bitANDC(tmp);
+
+ Uint32 retVal = 0;
+ NdbNodeBitmask report_mask;
+
+ if ((c_start.m_latest_gci == 0) ||
+ (c_start.m_start_type == (1 << NodeState::ST_INITIAL_START)))
+ {
+ if (!tmp.equal(c_definedNodes))
+ {
+ jam();
+ signal->theData[1] = 1;
+ signal->theData[2] = ~0;
+ report_mask.assign(wait);
+ retVal = 0;
+ goto start_report;
+ }
+ else
+ {
+ jam();
+ signal->theData[1] = 0x8000;
+ report_mask.assign(c_definedNodes);
+ report_mask.bitANDC(c_start.m_starting_nodes);
+ retVal = 1;
+ goto start_report;
+ }
+ }
+ {
+ const bool all = c_start.m_starting_nodes.equal(c_definedNodes);
+ CheckNodeGroups* sd = (CheckNodeGroups*)&signal->theData[0];
+
+ {
+ /**
+ * Check for missing node group directly
+ */
+ char buf[100];
+ NdbNodeBitmask check;
+ check.assign(c_definedNodes);
+ check.bitANDC(c_start.m_starting_nodes); // Not connected nodes
+ check.bitOR(c_start.m_starting_nodes_w_log);
+
+ sd->blockRef = reference();
+ sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
+ sd->mask = check;
+ EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
+ CheckNodeGroups::SignalLength);
+
+ if (sd->output == CheckNodeGroups::Lose)
+ {
+ jam();
+ goto missing_nodegroup;
+ }
+ }
+
+ sd->blockRef = reference();
+ sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
+ sd->mask = c_start.m_starting_nodes;
+ EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
+ CheckNodeGroups::SignalLength);
+
+ const Uint32 result = sd->output;
+
+ sd->blockRef = reference();
+ sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::ArbitCheck;
+ sd->mask = c_start.m_starting_nodes_w_log;
+ EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
+ CheckNodeGroups::SignalLength);
+
+ const Uint32 result_w_log = sd->output;
+
+ if (tmp.equal(c_definedNodes))
+ {
+ /**
+ * All nodes (wrt no-wait nodes) has connected...
+ * this means that we will now start or die
+ */
+ jam();
+ switch(result_w_log){
+ case CheckNodeGroups::Lose:
+ {
+ jam();
+ goto missing_nodegroup;
+ }
+ case CheckNodeGroups::Win:
+ signal->theData[1] = all ? 0x8001 : 0x8002;
+ report_mask.assign(c_definedNodes);
+ report_mask.bitANDC(c_start.m_starting_nodes);
+ retVal = 1;
+ goto start_report;
+ case CheckNodeGroups::Partitioning:
+ ndbrequire(result != CheckNodeGroups::Lose);
+ signal->theData[1] =
+ all ? 0x8001 : (result == CheckNodeGroups::Win ? 0x8002 : 0x8003);
+ report_mask.assign(c_definedNodes);
+ report_mask.bitANDC(c_start.m_starting_nodes);
+ retVal = 1;
+ goto start_report;
+ }
+ }
+
+ if (now < partial_timeout)
+ {
+ jam();
+ signal->theData[1] = c_restartPartialTimeout == ~0 ? 2 : 3;
+ signal->theData[2] = Uint32((partial_timeout - now + 500) / 1000);
+ report_mask.assign(wait);
+ retVal = 0;
+ goto start_report;
+ }
+
+ /**
+ * Start partial has passed...check for partitioning...
+ */
+ switch(result_w_log){
+ case CheckNodeGroups::Lose:
+ jam();
+ goto missing_nodegroup;
+ case CheckNodeGroups::Partitioning:
+ if (now < partitioned_timeout && result != CheckNodeGroups::Win)
+ {
+ signal->theData[1] = c_restartPartionedTimeout == ~0 ? 4 : 5;
+ signal->theData[2] = Uint32((partitioned_timeout - now + 500) / 1000);
+ report_mask.assign(c_definedNodes);
+ report_mask.bitANDC(c_start.m_starting_nodes);
+ retVal = 0;
+ goto start_report;
+ }
+ // Fall through...
+ case CheckNodeGroups::Win:
+ signal->theData[1] =
+ all ? 0x8001 : (result == CheckNodeGroups::Win ? 0x8002 : 0x8003);
+ report_mask.assign(c_definedNodes);
+ report_mask.bitANDC(c_start.m_starting_nodes);
+ retVal = 1;
+ goto start_report;
+ }
+ }
+ ndbrequire(false);
+
+start_report:
+ jam();
+ {
+ Uint32 sz = NdbNodeBitmask::Size;
+ signal->theData[0] = NDB_LE_StartReport;
+ signal->theData[3] = sz;
+ Uint32* ptr = signal->theData+4;
+ c_definedNodes.copyto(sz, ptr); ptr += sz;
+ c_start.m_starting_nodes.copyto(sz, ptr); ptr += sz;
+ c_start.m_skip_nodes.copyto(sz, ptr); ptr += sz;
+ report_mask.copyto(sz, ptr); ptr+= sz;
+ sendSignal(CMVMI_REF, GSN_EVENT_REP, signal,
+ 4+4*NdbNodeBitmask::Size, JBB);
+ }
+ return retVal;
+
+missing_nodegroup:
+ jam();
+ char buf[100], mask1[100], mask2[100];
+ c_start.m_starting_nodes.getText(mask1);
+ tmp.assign(c_start.m_starting_nodes);
+ tmp.bitANDC(c_start.m_starting_nodes_w_log);
+ tmp.getText(mask2);
+ BaseString::snprintf(buf, sizeof(buf),
+ "Unable to start missing node group! "
+ " starting: %s (missing fs for: %s)",
+ mask1, mask2);
+ progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf);
+}
+
void
Qmgr::electionWon(Signal* signal){
NodeRecPtr myNodePtr;
@@ -978,14 +1376,21 @@ Qmgr::electionWon(Signal* signal){
c_clusterNodes.set(getOwnNodeId());
cpresidentAlive = ZTRUE;
- c_stopElectionTime = ~0;
+ c_start_election_time = ~0;
c_start.reset();
- signal->theData[0] = EventReport::CM_REGCONF;
+ signal->theData[0] = NDB_LE_CM_REGCONF;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = cpresident;
signal->theData[3] = 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
+
+ c_start.m_starting_nodes.clear(getOwnNodeId());
+ if (c_start.m_starting_nodes.isclear())
+ {
+ jam();
+ sendSttorryLab(signal);
+ }
}
/*
@@ -999,7 +1404,14 @@ Qmgr::electionWon(Signal* signal){
/*--------------------------------------------------------------*/
void Qmgr::regreqTimeLimitLab(Signal* signal)
{
- if(cpresident == ZNIL){
+ if(cpresident == ZNIL)
+ {
+ if (c_start.m_president_candidate == ZNIL)
+ {
+ jam();
+ c_start.m_president_candidate = getOwnNodeId();
+ }
+
cmInfoconf010Lab(signal);
}
}//Qmgr::regreqTimelimitLab()
@@ -1239,7 +1651,7 @@ void Qmgr::execCM_ADD(Signal* signal)
jam();
ndbrequire(addNodePtr.p->phase == ZSTARTING);
addNodePtr.p->phase = ZRUNNING;
- addNodePtr.p->alarmCount = 0;
+ setNodeInfo(addNodePtr.i).m_heartbeat_cnt= 0;
c_clusterNodes.set(addNodePtr.i);
findNeighbours(signal);
@@ -1277,7 +1689,7 @@ Qmgr::joinedCluster(Signal* signal, NodeRecPtr nodePtr){
* NODES IN THE CLUSTER.
*/
nodePtr.p->phase = ZRUNNING;
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
findNeighbours(signal);
c_clusterNodes.set(nodePtr.i);
c_start.reset();
@@ -1409,6 +1821,17 @@ void Qmgr::execCM_ACKADD(Signal* signal)
*/
handleArbitNdbAdd(signal, addNodePtr.i);
c_start.reset();
+
+ if (c_start.m_starting_nodes.get(addNodePtr.i))
+ {
+ jam();
+ c_start.m_starting_nodes.clear(addNodePtr.i);
+ if (c_start.m_starting_nodes.isclear())
+ {
+ jam();
+ sendSttorryLab(signal);
+ }
+ }
return;
}//switch
ndbrequire(false);
@@ -1498,11 +1921,11 @@ void Qmgr::findNeighbours(Signal* signal)
*---------------------------------------------------------------------*/
fnNodePtr.i = cneighbourl;
ptrCheckGuard(fnNodePtr, MAX_NDB_NODES, nodeRec);
- fnNodePtr.p->alarmCount = 0;
+ setNodeInfo(fnNodePtr.i).m_heartbeat_cnt= 0;
}//if
}//if
- signal->theData[0] = EventReport::FIND_NEIGHBOURS;
+ signal->theData[0] = NDB_LE_FIND_NEIGHBOURS;
signal->theData[1] = getOwnNodeId();
signal->theData[2] = cneighbourl;
signal->theData[3] = cneighbourh;
@@ -1546,8 +1969,8 @@ void Qmgr::initData(Signal* signal)
} else {
nodePtr.p->phase = ZAPI_INACTIVE;
}
-
- nodePtr.p->alarmCount = 0;
+
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
nodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
nodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
nodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
@@ -1562,7 +1985,8 @@ void Qmgr::initData(Signal* signal)
cnoPrepFailedNodes = 0;
creadyDistCom = ZFALSE;
cpresident = ZNIL;
- cpresidentCandidate = ZNIL;
+ c_start.m_president_candidate = ZNIL;
+ c_start.m_president_candidate_gci = 0;
cpdistref = 0;
cneighbourh = ZNIL;
cneighbourl = ZNIL;
@@ -1590,15 +2014,33 @@ void Qmgr::initData(Signal* signal)
Uint32 hbDBAPI = 1500;
Uint32 arbitTimeout = 1000;
c_restartPartialTimeout = 30000;
+ c_restartPartionedTimeout = 60000;
+ c_restartFailureTimeout = ~0;
ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &hbDBDB);
ndb_mgm_get_int_parameter(p, CFG_DB_API_HEARTBEAT_INTERVAL, &hbDBAPI);
ndb_mgm_get_int_parameter(p, CFG_DB_ARBIT_TIMEOUT, &arbitTimeout);
ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTIAL_TIMEOUT,
&c_restartPartialTimeout);
- if(c_restartPartialTimeout == 0){
+ ndb_mgm_get_int_parameter(p, CFG_DB_START_PARTITION_TIMEOUT,
+ &c_restartPartionedTimeout);
+ ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT,
+ &c_restartFailureTimeout);
+
+ if(c_restartPartialTimeout == 0)
+ {
c_restartPartialTimeout = ~0;
}
+ if (c_restartPartionedTimeout ==0)
+ {
+ c_restartPartionedTimeout = ~0;
+ }
+
+ if (c_restartFailureTimeout == 0)
+ {
+ c_restartFailureTimeout = ~0;
+ }
+
setHbDelay(hbDBDB);
setHbApiDelay(hbDBAPI);
setArbitTimeout(arbitTimeout);
@@ -1728,7 +2170,7 @@ void Qmgr::sendHeartbeat(Signal* signal)
sendSignal(localNodePtr.p->blockRef, GSN_CM_HEARTBEAT, signal, 1, JBA);
#ifdef VM_TRACE
- signal->theData[0] = EventReport::SentHeartbeat;
+ signal->theData[0] = NDB_LE_SentHeartbeat;
signal->theData[1] = localNodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
#endif
@@ -1749,24 +2191,24 @@ void Qmgr::checkHeartbeat(Signal* signal)
}//if
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
- nodePtr.p->alarmCount ++;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt++;
ndbrequire(nodePtr.p->phase == ZRUNNING);
ndbrequire(getNodeInfo(nodePtr.i).m_type == NodeInfo::DB);
- if(nodePtr.p->alarmCount > 2){
- signal->theData[0] = EventReport::MissedHeartbeat;
+ if(getNodeInfo(nodePtr.i).m_heartbeat_cnt > 2){
+ signal->theData[0] = NDB_LE_MissedHeartbeat;
signal->theData[1] = nodePtr.i;
- signal->theData[2] = nodePtr.p->alarmCount - 1;
+ signal->theData[2] = getNodeInfo(nodePtr.i).m_heartbeat_cnt - 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
- if (nodePtr.p->alarmCount > 4) {
+ if (getNodeInfo(nodePtr.i).m_heartbeat_cnt > 4) {
jam();
/**----------------------------------------------------------------------
* OUR LEFT NEIGHBOUR HAVE KEPT QUIET FOR THREE CONSECUTIVE HEARTBEAT
* PERIODS. THUS WE DECLARE HIM DOWN.
*----------------------------------------------------------------------*/
- signal->theData[0] = EventReport::DeadDueToHeartbeat;
+ signal->theData[0] = NDB_LE_DeadDueToHeartbeat;
signal->theData[1] = nodePtr.i;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -1792,16 +2234,16 @@ void Qmgr::apiHbHandlingLab(Signal* signal)
if (TnodePtr.p->phase == ZAPI_ACTIVE){
jam();
- TnodePtr.p->alarmCount ++;
+ setNodeInfo(TnodePtr.i).m_heartbeat_cnt++;
- if(TnodePtr.p->alarmCount > 2){
- signal->theData[0] = EventReport::MissedHeartbeat;
+ if(getNodeInfo(TnodePtr.i).m_heartbeat_cnt > 2){
+ signal->theData[0] = NDB_LE_MissedHeartbeat;
signal->theData[1] = nodeId;
- signal->theData[2] = TnodePtr.p->alarmCount - 1;
+ signal->theData[2] = getNodeInfo(TnodePtr.i).m_heartbeat_cnt - 1;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
}
- if (TnodePtr.p->alarmCount > 4) {
+ if (getNodeInfo(TnodePtr.i).m_heartbeat_cnt > 4) {
jam();
/*------------------------------------------------------------------*/
/* THE API NODE HAS NOT SENT ANY HEARTBEAT FOR THREE SECONDS.
@@ -1810,7 +2252,7 @@ void Qmgr::apiHbHandlingLab(Signal* signal)
/*------------------------------------------------------------------*/
/* We call node_failed to release all connections for this api node */
/*------------------------------------------------------------------*/
- signal->theData[0] = EventReport::DeadDueToHeartbeat;
+ signal->theData[0] = NDB_LE_DeadDueToHeartbeat;
signal->theData[1] = nodeId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
@@ -1833,16 +2275,17 @@ void Qmgr::checkStartInterface(Signal* signal)
ptrAss(nodePtr, nodeRec);
if (nodePtr.p->phase == ZFAIL_CLOSING) {
jam();
- nodePtr.p->alarmCount = nodePtr.p->alarmCount + 1;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt++;
if (c_connectedNodes.get(nodePtr.i)){
jam();
/*-------------------------------------------------------------------*/
// We need to ensure that the connection is not restored until it has
// been disconnected for at least three seconds.
/*-------------------------------------------------------------------*/
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
}//if
- if ((nodePtr.p->alarmCount > 3) && (nodePtr.p->failState == NORMAL)) {
+ if ((getNodeInfo(nodePtr.i).m_heartbeat_cnt > 3)
+ && (nodePtr.p->failState == NORMAL)) {
/**------------------------------------------------------------------
* WE HAVE DISCONNECTED THREE SECONDS AGO. WE ARE NOW READY TO
* CONNECT AGAIN AND ACCEPT NEW REGISTRATIONS FROM THIS NODE.
@@ -1858,18 +2301,18 @@ void Qmgr::checkStartInterface(Signal* signal)
nodePtr.p->phase = ZINIT;
}//if
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
signal->theData[0] = 0;
signal->theData[1] = nodePtr.i;
sendSignal(CMVMI_REF, GSN_OPEN_COMREQ, signal, 2, JBA);
} else {
- if(((nodePtr.p->alarmCount + 1) % 60) == 0){
+ if(((getNodeInfo(nodePtr.i).m_heartbeat_cnt + 1) % 60) == 0){
char buf[100];
BaseString::snprintf(buf, sizeof(buf),
"Failure handling of node %d has not completed in %d min."
" - state = %d",
nodePtr.i,
- (nodePtr.p->alarmCount + 1)/60,
+ (getNodeInfo(nodePtr.i).m_heartbeat_cnt + 1)/60,
nodePtr.p->failState);
warningEvent(buf);
}
@@ -1899,7 +2342,6 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo)
failedNodePtr.p->failState = WAITING_FOR_FAILCONF1;
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);
/**-------------------------------------------------------------------------
* THE OTHER NODE WAS AN API NODE. THE COMMUNICATION LINK IS ALREADY
@@ -1907,7 +2349,7 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo)
* WE ONLY NEED TO SET PARAMETERS TO ENABLE A NEW CONNECTION IN A FEW
* SECONDS.
*-------------------------------------------------------------------------*/
- failedNodePtr.p->alarmCount = 0;
+ setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
@@ -2015,31 +2457,52 @@ void Qmgr::execNDB_FAILCONF(Signal* signal)
/*******************************/
/* DISCONNECT_REP */
/*******************************/
+const char *lookupConnectionError(Uint32 err);
+
void Qmgr::execDISCONNECT_REP(Signal* signal)
{
jamEntry();
const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
const Uint32 nodeId = rep->nodeId;
+ const Uint32 err = rep->err;
c_connectedNodes.clear(nodeId);
c_readnodes_nodes.clear(nodeId);
NodeRecPtr nodePtr;
nodePtr.i = getOwnNodeId();
ptrCheckGuard(nodePtr, MAX_NODES, nodeRec);
+
+ char buf[100];
+ if (getNodeInfo(nodeId).getType() == NodeInfo::DB &&
+ getNodeState().startLevel < NodeState::SL_STARTED)
+ {
+ jam();
+ CRASH_INSERTION(932);
+ BaseString::snprintf(buf, 100, "Node %u disconnected", nodeId);
+ progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
+ ndbrequire(false);
+ }
+
switch(nodePtr.p->phase){
case ZRUNNING:
jam();
break;
case ZINIT:
+ ndbrequire(false);
case ZSTARTING:
+ progError(__LINE__, NDBD_EXIT_CONNECTION_SETUP_FAILED,
+ lookupConnectionError(err));
+ ndbrequire(false);
case ZPREPARE_FAIL:
+ ndbrequire(false);
case ZFAIL_CLOSING:
+ ndbrequire(false);
case ZAPI_ACTIVE:
+ ndbrequire(false);
case ZAPI_INACTIVE:
{
- char buf[100];
- BaseString::snprintf(buf, 100, "Node %u disconected", nodeId);
- progError(__LINE__, ERR_SR_OTHERNODEFAILED, buf);
+ BaseString::snprintf(buf, 100, "Node %u disconnected", nodeId);
+ progError(__LINE__, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
ndbrequire(false);
}
}
@@ -2081,7 +2544,7 @@ void Qmgr::node_failed(Signal* signal, Uint16 aFailedNode)
/*---------------------------------------------------------------------*/
failedNodePtr.p->failState = NORMAL;
failedNodePtr.p->phase = ZFAIL_CLOSING;
- failedNodePtr.p->alarmCount = 0;
+ setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
CloseComReqConf * const closeCom =
(CloseComReqConf *)&signal->theData[0];
@@ -2175,8 +2638,8 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
}
setNodeInfo(apiNodePtr.i).m_version = version;
-
- apiNodePtr.p->alarmCount = 0;
+
+ setNodeInfo(apiNodePtr.i).m_heartbeat_cnt= 0;
ApiRegConf * const apiRegConf = (ApiRegConf *)&signal->theData[0];
apiRegConf->qmgrRef = reference();
@@ -2217,29 +2680,32 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
}//Qmgr::execAPI_REGREQ()
-void
+void
Qmgr::execAPI_VERSION_REQ(Signal * signal) {
jamEntry();
ApiVersionReq * const req = (ApiVersionReq *)signal->getDataPtr();
-
+
Uint32 senderRef = req->senderRef;
Uint32 nodeId = req->nodeId;
ApiVersionConf * conf = (ApiVersionConf *)req;
if(getNodeInfo(nodeId).m_connected)
+ {
conf->version = getNodeInfo(nodeId).m_version;
+ struct in_addr in= globalTransporterRegistry.get_connect_address(nodeId);
+ conf->inet_addr= in.s_addr;
+ }
else
+ {
conf->version = 0;
+ conf->inet_addr= 0;
+ }
conf->nodeId = nodeId;
- struct in_addr in= globalTransporterRegistry.get_connect_address(nodeId);
- conf->inet_addr= in.s_addr;
- sendSignal(senderRef,
+ sendSignal(senderRef,
GSN_API_VERSION_CONF,
signal,
ApiVersionConf::SignalLength, JBB);
-
-
}
@@ -2330,7 +2796,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
break;
case FailRep::ZPARTITIONED_CLUSTER:
{
- code = ERR_ARBIT_SHUTDOWN;
+ code = NDBD_EXIT_PARTITIONED_SHUTDOWN;
char buf1[100], buf2[100];
c_clusterNodes.getText(buf1);
if (signal->getLength()== FailRep::SignalLength + FailRep::ExtraLength &&
@@ -2341,20 +2807,23 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
part.assign(NdbNodeBitmask::Size, rep->partition);
part.getText(buf2);
BaseString::snprintf(extra, sizeof(extra),
- "Partitioned cluster!"
- " Our cluster: %s other cluster: %s",
+ "Our cluster: %s other cluster: %s",
buf1, buf2);
}
else
{
jam();
BaseString::snprintf(extra, sizeof(extra),
- "Partitioned cluster!"
- " Our cluster: %s ", buf1);
+ "Our cluster: %s", buf1);
}
msg = extra;
break;
}
+ case FailRep::ZMULTI_NODE_SHUTDOWN:
+ msg = "Multi node shutdown";
+ break;
+ default:
+ msg = "<UNKNOWN>";
}
CRASH_INSERTION(932);
@@ -2773,7 +3242,7 @@ void Qmgr::execCOMMIT_FAILREQ(Signal* signal)
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRec);
nodePtr.p->phase = ZFAIL_CLOSING;
nodePtr.p->failState = WAITING_FOR_NDB_FAILCONF;
- nodePtr.p->alarmCount = 0;
+ setNodeInfo(nodePtr.i).m_heartbeat_cnt= 0;
c_clusterNodes.clear(nodePtr.i);
}//for
/*----------------------------------------------------------------------*/
@@ -2975,7 +3444,7 @@ void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line,
"Node was shutdown during startup because node %d failed",
failedNodeId);
- progError(line, ERR_SR_OTHERNODEFAILED, buf);
+ progError(line, NDBD_EXIT_SR_OTHERNODEFAILED, buf);
}
@@ -2987,7 +3456,7 @@ void Qmgr::systemErrorLab(Signal* signal, Uint32 line, const char * message)
// If it's known why shutdown occured
// an error message has been passed to this function
- progError(line, 0, message);
+ progError(line, NDBD_EXIT_NDBREQUIRE, message);
return;
}//Qmgr::systemErrorLab()
@@ -3031,7 +3500,7 @@ void Qmgr::failReport(Signal* signal,
failedNodePtr.p->sendPrepFailReqStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendCommitFailReqStatus = Q_NOT_ACTIVE;
failedNodePtr.p->sendPresToStatus = Q_NOT_ACTIVE;
- failedNodePtr.p->alarmCount = 0;
+ setNodeInfo(failedNodePtr.i).m_heartbeat_cnt= 0;
if (aSendFailRep == ZTRUE) {
jam();
if (failedNodePtr.i != getOwnNodeId()) {
@@ -3356,7 +3825,7 @@ Qmgr::handleArbitApiFail(Signal* signal, Uint16 nodeId)
jam();
return;
}
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.node = 0;
switch (arbitRec.state) {
case ARBIT_NULL: // should not happen
@@ -3527,7 +3996,7 @@ Qmgr::handleArbitCheck(Signal* signal)
arbitRec.newstate = true;
break;
}
- reportArbitEvent(signal, EventReport::ArbitResult);
+ reportArbitEvent(signal, NDB_LE_ArbitResult);
switch (arbitRec.state) {
default:
jam();
@@ -3554,7 +4023,7 @@ Qmgr::startArbitThread(Signal* signal)
jam();
ndbrequire(cpresident == getOwnNodeId());
arbitRec.code = ArbitCode::ThreadStart;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
signal->theData[1] = ++arbitRec.thread;
runArbitThread(signal);
}
@@ -3798,7 +4267,7 @@ Qmgr::execARBIT_PREPREQ(Signal* signal)
arbitRec.node = sd->node;
arbitRec.ticket = sd->ticket;
arbitRec.code = sd->code;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.state = ARBIT_RUN;
arbitRec.newstate = true;
if (sd->code == ArbitCode::PrepAtrun) {
@@ -3885,7 +4354,7 @@ Qmgr::stateArbitStart(Signal* signal)
}
if (arbitRec.recvCount) {
jam();
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
if (arbitRec.code == ArbitCode::ApiStart) {
jam();
arbitRec.state = ARBIT_RUN;
@@ -3899,7 +4368,7 @@ Qmgr::stateArbitStart(Signal* signal)
if (arbitRec.getTimediff() > getArbitTimeout()) {
jam();
arbitRec.code = ArbitCode::ErrTimeout;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.state = ARBIT_INIT;
arbitRec.newstate = true;
return;
@@ -4006,7 +4475,7 @@ Qmgr::stateArbitChoose(Signal* signal)
}
if (arbitRec.recvCount) {
jam();
- reportArbitEvent(signal, EventReport::ArbitResult);
+ reportArbitEvent(signal, NDB_LE_ArbitResult);
if (arbitRec.code == ArbitCode::WinChoose) {
jam();
sendCommitFailReq(signal); // start commit of failed nodes
@@ -4022,7 +4491,7 @@ Qmgr::stateArbitChoose(Signal* signal)
if (arbitRec.getTimediff() > getArbitTimeout()) {
jam();
arbitRec.code = ArbitCode::ErrTimeout;
- reportArbitEvent(signal, EventReport::ArbitState);
+ reportArbitEvent(signal, NDB_LE_ArbitState);
arbitRec.state = ARBIT_CRASH;
arbitRec.newstate = true;
stateArbitCrash(signal); // do it at once
@@ -4083,8 +4552,8 @@ Qmgr::stateArbitCrash(Signal* signal)
return;
#endif
CRASH_INSERTION(932);
-
- progError(__LINE__, ERR_ARBIT_SHUTDOWN, "Arbitrator decided to shutdown this node");
+ progError(__LINE__, NDBD_EXIT_ARBIT_SHUTDOWN,
+ "Arbitrator decided to shutdown this node");
}
/**
@@ -4125,7 +4594,7 @@ Qmgr::computeArbitNdbMask(NodeBitmask& aMask)
* where sender (word 0) is event type.
*/
void
-Qmgr::reportArbitEvent(Signal* signal, EventReport::EventType type)
+Qmgr::reportArbitEvent(Signal* signal, Ndb_logevent_type type)
{
ArbitSignalData* sd = (ArbitSignalData*)&signal->theData[0];
sd->sender = type;
@@ -4146,8 +4615,10 @@ Qmgr::execDUMP_STATE_ORD(Signal* signal)
case 1:
infoEvent("creadyDistCom = %d, cpresident = %d\n",
creadyDistCom, cpresident);
- infoEvent("cpresidentAlive = %d, cpresidentCand = %d\n",
- cpresidentAlive, cpresidentCandidate);
+ infoEvent("cpresidentAlive = %d, cpresidentCand = %d (gci: %d)\n",
+ cpresidentAlive,
+ c_start.m_president_candidate,
+ c_start.m_president_candidate_gci);
infoEvent("ctoStatus = %d\n", ctoStatus);
for(Uint32 i = 1; i<MAX_NDB_NODES; i++){
if(getNodeInfo(i).getType() == NodeInfo::DB){
diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp
index 84a59f440d9..449436331e4 100644
--- a/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -50,6 +50,17 @@
//#define EVENT_DEBUG
//#define EVENT_PH3_DEBUG
//#define EVENT_DEBUG2
+#if 0
+#undef DBUG_ENTER
+#undef DBUG_PRINT
+#undef DBUG_RETURN
+#undef DBUG_VOID_RETURN
+
+#define DBUG_ENTER(a) {ndbout_c("%s:%d >%s", __FILE__, __LINE__, a);}
+#define DBUG_PRINT(a,b) {ndbout << __FILE__ << ":" << __LINE__ << " " << a << ": "; ndbout_c b ;}
+#define DBUG_RETURN(a) { ndbout_c("%s:%d <", __FILE__, __LINE__); return(a); }
+#define DBUG_VOID_RETURN { ndbout_c("%s:%d <", __FILE__, __LINE__); return; }
+#endif
/**
* @todo:
@@ -71,61 +82,73 @@ static const Uint32 SUMA_SEQUENCE = 0xBABEBABE;
#define PRINT_ONLY 0
static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
-void
-Suma::getNodeGroupMembers(Signal* signal) {
- jam();
+void
+Suma::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
+
+ // SumaParticipant
+ Uint32 noTables;
+ ndb_mgm_get_int_parameter(p, CFG_DB_NO_TABLES,
+ &noTables);
+
/**
- * Ask DIH for nodeGroupMembers
+ * @todo: fix pool sizes
*/
- CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
- sd->blockRef = reference();
- sd->requestType =
- CheckNodeGroups::Direct |
- CheckNodeGroups::GetNodeGroupMembers;
- sd->nodeId = getOwnNodeId();
- EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
- CheckNodeGroups::SignalLength);
- jamEntry();
+ c_tablePool_.setSize(noTables);
+ c_tables.setSize(noTables);
- c_nodeGroup = sd->output;
- c_noNodesInGroup = 0;
- for (int i = 0; i < MAX_NDB_NODES; i++) {
- if (sd->mask.get(i)) {
- if (i == getOwnNodeId()) c_idInNodeGroup = c_noNodesInGroup;
- c_nodesInGroup[c_noNodesInGroup] = i;
- c_noNodesInGroup++;
- }
+ c_subscriptions.setSize(20); //10
+ c_subscriberPool.setSize(64);
+
+ c_subscriptionPool.setSize(64); //2
+ c_syncPool.setSize(20); //2
+ c_dataBufferPool.setSize(128);
+
+ {
+ SLList<SyncRecord> tmp(c_syncPool);
+ Ptr<SyncRecord> ptr;
+ while(tmp.seize(ptr))
+ new (ptr.p) SyncRecord(* this, c_dataBufferPool);
+ tmp.release();
}
- // ndbout_c("c_noNodesInGroup=%d", c_noNodesInGroup);
- ndbrequire(c_noNodesInGroup > 0); // at least 1 node in the nodegroup
+ // Suma
+ c_nodePool.setSize(MAX_NDB_NODES);
+ c_masterNodeId = getOwnNodeId();
-#ifdef NODEFAIL_DEBUG
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- ndbout_c ("Suma: NodeGroup %u, me %u, me in group %u, member[%u] %u",
- c_nodeGroup, getOwnNodeId(), c_idInNodeGroup,
- i, c_nodesInGroup[i]);
+ c_nodeGroup = c_noNodesInGroup = c_idInNodeGroup = 0;
+ for (int i = 0; i < MAX_REPLICAS; i++) {
+ c_nodesInGroup[i] = 0;
}
-#endif
+
+ c_subCoordinatorPool.setSize(10);
+
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
}
void
Suma::execSTTOR(Signal* signal) {
jamEntry();
-
+
+ DBUG_ENTER("Suma::execSTTOR");
const Uint32 startphase = signal->theData[1];
const Uint32 typeOfStart = signal->theData[7];
-#ifdef NODEFAIL_DEBUG
- ndbout_c ("SUMA::execSTTOR startphase = %u, typeOfStart = %u",
- startphase, typeOfStart);
-
-#endif
-
- if(startphase == 1){
- jam();
- c_restartLock = true;
- }
+ DBUG_PRINT("info",("startphase = %u, typeOfStart = %u", startphase, typeOfStart));
if(startphase == 3){
jam();
@@ -155,67 +178,39 @@ Suma::execSTTOR(Signal* signal) {
g_subPtrI = subPtr.i;
// sendSTTORRY(signal);
#endif
- return;
+ DBUG_VOID_RETURN;
}
- if(startphase == 5) {
- getNodeGroupMembers(signal);
- if (g_TypeOfStart == NodeState::ST_NODE_RESTART) {
- jam();
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- Uint32 ref = calcSumaBlockRef(c_nodesInGroup[i]);
- if (ref != reference())
- sendSignal(ref, GSN_SUMA_START_ME, signal,
- 1 /*SumaStartMe::SignalLength*/, JBB);
- }
- }
- }
-
if(startphase == 7) {
- c_restartLock = false; // may be set false earlier with HANDOVER_REQ
-
- if (g_TypeOfStart != NodeState::ST_NODE_RESTART) {
- for( int i = 0; i < NO_OF_BUCKETS; i++) {
- if (getResponsibleSumaNodeId(i) == refToNode(reference())) {
- // I'm running this bucket
-#ifdef EVENT_DEBUG
- ndbout_c("bucket %u set to true", i);
-#endif
- c_buckets[i].active = true;
- }
- }
- }
-
if(g_TypeOfStart == NodeState::ST_INITIAL_START &&
c_masterNodeId == getOwnNodeId()) {
jam();
createSequence(signal);
- return;
+ DBUG_VOID_RETURN;
}//if
}//if
sendSTTORRY(signal);
- return;
+ DBUG_VOID_RETURN;
}
void
Suma::createSequence(Signal* signal)
{
jam();
+ DBUG_ENTER("Suma::createSequence");
UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
req->senderData = RNIL;
req->sequenceId = SUMA_SEQUENCE;
req->requestType = UtilSequenceReq::Create;
-#ifdef DEBUG_SUMA_SEQUENCE
- ndbout_c("SUMA: Create sequence");
-#endif
sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
signal, UtilSequenceReq::SignalLength, JBB);
// execUTIL_SEQUENCE_CONF will call createSequenceReply()
+ DBUG_VOID_RETURN;
}
void
@@ -267,40 +262,6 @@ 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;
@@ -335,269 +296,6 @@ SumaParticipant::execCONTINUEB(Signal* signal)
*
*****************************************************************************/
-void Suma::execAPI_FAILREQ(Signal* signal)
-{
- jamEntry();
- Uint32 failedApiNode = signal->theData[0];
- //BlockReference retRef = signal->theData[1];
-
- c_failedApiNodes.set(failedApiNode);
- bool found = removeSubscribersOnNode(signal, failedApiNode);
-
- if(!found){
- jam();
- c_failedApiNodes.clear(failedApiNode);
- }
-}//execAPI_FAILREQ()
-
-bool
-SumaParticipant::removeSubscribersOnNode(Signal *signal, Uint32 nodeId)
-{
- bool found = false;
-
- SubscriberPtr i_subbPtr;
- c_dataSubscribers.first(i_subbPtr);
- while(!i_subbPtr.isNull()){
- SubscriberPtr subbPtr = i_subbPtr;
- c_dataSubscribers.next(i_subbPtr);
- jam();
- if (refToNode(subbPtr.p->m_subscriberRef) == nodeId) {
- jam();
- c_dataSubscribers.remove(subbPtr);
- c_removeDataSubscribers.add(subbPtr);
- found = true;
- }
- }
- if(found){
- jam();
- sendSubStopReq(signal);
- }
- return found;
-}
-
-void
-SumaParticipant::sendSubStopReq(Signal *signal){
- static bool remove_lock = false;
- jam();
-
- if(remove_lock) {
- jam();
- return;
- }
- remove_lock = true;
-
- SubscriberPtr subbPtr;
- c_removeDataSubscribers.first(subbPtr);
- if (subbPtr.isNull()){
- jam();
-#if 0
- signal->theData[0] = failedApiNode;
- signal->theData[1] = reference();
- sendSignal(retRef, GSN_API_FAILCONF, signal, 2, JBB);
-#endif
- c_failedApiNodes.clear();
-
- remove_lock = false;
- return;
- }
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-
- SubStopReq * const req = (SubStopReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = subbPtr.i;
- req->subscriberRef = subbPtr.p->m_subscriberRef;
- req->subscriberData = subbPtr.p->m_subscriberData;
- req->subscriptionId = subPtr.p->m_subscriptionId;
- req->subscriptionKey = subPtr.p->m_subscriptionKey;
- req->part = SubscriptionData::TableData;
-
- sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
-}
-
-void
-SumaParticipant::execSUB_STOP_CONF(Signal* signal){
- jamEntry();
-
- SubStopConf * const conf = (SubStopConf*)signal->getDataPtr();
-
- // Uint32 subscriberData = conf->subscriberData;
- // Uint32 subscriberRef = conf->subscriberRef;
-
- Subscription key;
- key.m_subscriptionId = conf->subscriptionId;
- key.m_subscriptionKey = conf->subscriptionKey;
-
- SubscriptionPtr subPtr;
- if(c_subscriptions.find(subPtr, key)) {
- jam();
- if (subPtr.p->m_markRemove) {
- jam();
- ndbrequire(false);
- ndbrequire(subPtr.p->m_nSubscribers > 0);
- subPtr.p->m_nSubscribers--;
- if (subPtr.p->m_nSubscribers == 0){
- jam();
- completeSubRemoveReq(signal, subPtr);
- }
- }
- }
-
- sendSubStopReq(signal);
-}
-
-void
-SumaParticipant::execSUB_STOP_REF(Signal* signal){
- jamEntry();
- SubStopRef * const ref = (SubStopRef*)signal->getDataPtr();
-
- Uint32 subscriptionId = ref->subscriptionId;
- Uint32 subscriptionKey = ref->subscriptionKey;
- Uint32 part = ref->part;
- Uint32 subscriberData = ref->subscriberData;
- Uint32 subscriberRef = ref->subscriberRef;
- // Uint32 err = ref->err;
-
- if(!ref->isTemporary()){
- ndbrequire(false);
- }
-
- SubStopReq * const req = (SubStopReq*)signal->getDataPtrSend();
- req->subscriberRef = subscriberRef;
- req->subscriberData = subscriberData;
- req->subscriptionId = subscriptionId;
- req->subscriptionKey = subscriptionKey;
- req->part = part;
-
- sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
-}
-
-void
-Suma::execNODE_FAILREP(Signal* signal){
- jamEntry();
-
- NodeFailRep * const rep = (NodeFailRep*)signal->getDataPtr();
-
- bool changed = false;
-
- NodePtr nodePtr;
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma: nodefailrep");
-#endif
- c_nodeFailGCI = getFirstGCI(signal);
-
- for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)){
- if(NodeBitmask::get(rep->theNodes, nodePtr.p->nodeId)){
- if(nodePtr.p->alive){
- ndbassert(c_aliveNodes.get(nodePtr.p->nodeId));
- changed = true;
- jam();
- } else {
- ndbassert(!c_aliveNodes.get(nodePtr.p->nodeId));
- jam();
- }
-
- if (c_preparingNodes.get(nodePtr.p->nodeId)) {
- jam();
- // we are currently preparing this node that died
- // it's ok just to clear and go back to waiting for it to start up
- Restart.resetNode(calcSumaBlockRef(nodePtr.p->nodeId));
- c_preparingNodes.clear(nodePtr.p->nodeId);
- } else if (c_handoverToDo) {
- jam();
- // TODO what if I'm a SUMA that is currently restarting and the SUMA
- // responsible for restarting me is the one that died?
-
- // a node has failed whilst handover is going on
- // let's check if we're in the process of handover with that node
- c_handoverToDo = false;
- for( int i = 0; i < NO_OF_BUCKETS; i++) {
- if (c_buckets[i].handover) {
- // I'm doing handover, but is it with the dead node?
- if (getResponsibleSumaNodeId(i) == nodePtr.p->nodeId) {
- // so it was the dead node, has handover started?
- if (c_buckets[i].handover_started) {
- jam();
- // we're not ok and will have lost data!
- // set not active to indicate this -
- // this will generate takeover behaviour
- c_buckets[i].active = false;
- c_buckets[i].handover_started = false;
- } // else we're ok to revert back to state before
- c_buckets[i].handover = false;
- } else {
- jam();
- // ok, we're doing handover with a different node
- c_handoverToDo = true;
- }
- }
- }
- }
-
- c_failoverBuffer.nodeFailRep();
-
- nodePtr.p->alive = 0;
- c_aliveNodes.clear(nodePtr.p->nodeId); // this has to be done after the loop above
- }
- }
-}
-
-void
-Suma::execINCL_NODEREQ(Signal* signal){
- jamEntry();
-
- //const Uint32 senderRef = signal->theData[0];
- const Uint32 inclNode = signal->theData[1];
-
- NodePtr node;
- for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)){
- jam();
- const Uint32 nodeId = node.p->nodeId;
- if(inclNode == nodeId){
- jam();
-
- ndbrequire(node.p->alive == 0);
- ndbrequire(!c_aliveNodes.get(nodeId));
-
- for (Uint32 j = 0; j < c_noNodesInGroup; j++) {
- jam();
- if (c_nodesInGroup[j] == nodeId) {
- // the starting node is part of my node group
- jam();
- c_preparingNodes.set(nodeId); // set as being prepared
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- jam();
- if (i == c_idInNodeGroup) {
- jam();
- // I'm responsible for restarting this SUMA
- // ALL dict's should have meta data info so it is ok to start
- Restart.startNode(signal, calcSumaBlockRef(nodeId));
- break;
- }//if
- if (c_aliveNodes.get(c_nodesInGroup[i])) {
- jam();
- break; // another Suma takes care of this
- }//if
- }//for
- break;
- }//if
- }//for
-
- node.p->alive = 1;
- c_aliveNodes.set(nodeId);
-
- break;
- }//if
- }//for
-
-#if 0 // if we include this DIH's got to be prepared, later if needed...
- signal->theData[0] = reference();
-
- sendSignal(senderRef, GSN_INCL_NODECONF, signal, 1, JBB);
-#endif
-}
-
void
Suma::execSIGNAL_DROPPED_REP(Signal* signal){
jamEntry();
@@ -610,6 +308,19 @@ Suma::execSIGNAL_DROPPED_REP(Signal* signal){
*
*/
+static unsigned
+count_subscribers(const DLList<SumaParticipant::Subscriber> &subs)
+{
+ unsigned n= 0;
+ SumaParticipant::SubscriberPtr i_subbPtr;
+ subs.first(i_subbPtr);
+ while(!i_subbPtr.isNull()){
+ n++;
+ subs.next(i_subbPtr);
+ }
+ return n;
+}
+
void
Suma::execDUMP_STATE_ORD(Signal* signal){
jamEntry();
@@ -630,10 +341,6 @@ Suma::execDUMP_STATE_ORD(Signal* signal){
syncPtr.p->startScan(signal);
}
- 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);
@@ -664,6 +371,15 @@ Suma::execDUMP_STATE_ORD(Signal* signal){
infoEvent("Suma: c_dataBufferPool size: %d free: %d",
c_dataBufferPool.getSize(),
c_dataBufferPool.getNoOfFree());
+
+ infoEvent("Suma: c_metaSubscribers count: %d",
+ count_subscribers(c_metaSubscribers));
+ infoEvent("Suma: c_dataSubscribers count: %d",
+ count_subscribers(c_dataSubscribers));
+ infoEvent("Suma: c_prepDataSubscribers count: %d",
+ count_subscribers(c_prepDataSubscribers));
+ infoEvent("Suma: c_removeDataSubscribers count: %d",
+ count_subscribers(c_removeDataSubscribers));
}
}
@@ -812,16 +528,14 @@ Suma::execUTIL_SEQUENCE_CONF(Signal* signal)
{
jamEntry();
+ DBUG_ENTER("Suma::execUTIL_SEQUENCE_CONF");
CRASH_INSERTION(13002);
UtilSequenceConf * conf = (UtilSequenceConf*)signal->getDataPtr();
-#ifdef DEBUG_SUMA_SEQUENCE
- ndbout_c("SUMA: Create sequence conf");
-#endif
if(conf->requestType == UtilSequenceReq::Create) {
jam();
createSequenceReply(signal, conf, NULL);
- return;
+ DBUG_VOID_RETURN;
}
Uint64 subId;
@@ -841,18 +555,21 @@ Suma::execUTIL_SEQUENCE_CONF(Signal* signal)
CreateSubscriptionIdConf::SignalLength, JBB);
c_subscriberPool.release(subbPtr);
+
+ DBUG_VOID_RETURN;
}
void
Suma::execUTIL_SEQUENCE_REF(Signal* signal)
{
jamEntry();
+ DBUG_ENTER("Suma::execUTIL_SEQUENCE_REF");
UtilSequenceRef * ref = (UtilSequenceRef*)signal->getDataPtr();
if(ref->requestType == UtilSequenceReq::Create) {
jam();
createSequenceReply(signal, NULL, ref);
- return;
+ DBUG_VOID_RETURN;
}
Uint32 subData = ref->senderData;
@@ -861,7 +578,7 @@ Suma::execUTIL_SEQUENCE_REF(Signal* signal)
c_subscriberPool.getPtr(subbPtr,subData);
sendSubIdRef(signal, GrepError::SEQUENCE_ERROR);
c_subscriberPool.release(subbPtr);
- return;
+ DBUG_VOID_RETURN;
}//execUTIL_SEQUENCE_REF()
@@ -1089,26 +806,6 @@ SumaParticipant::sendSubCreateRef(Signal* signal, const SubCreateReq& req, Uint3
return;
}
-
-
-
-
-
-
-
-
-
-
-
-Uint32
-SumaParticipant::getFirstGCI(Signal* signal) {
- if (c_lastCompleteGCI == RNIL) {
- ndbout_c("WARNING: c_lastCompleteGCI == RNIL");
- return 0;
- }
- return c_lastCompleteGCI+3;
-}
-
/**********************************************************
*
* Setting upp trigger for subscription
@@ -1154,27 +851,6 @@ SumaParticipant::execSUB_SYNC_REQ(Signal* signal) {
case SubscriptionData::MetaData:
ok = true;
jam();
- if (subPtr.p->m_subscriptionType == SubCreateReq::DatabaseSnapshot) {
- TableList::DataBufferIterator it;
- syncPtr.p->m_tableList.first(it);
- if(it.isNull()) {
- /**
- * Get all tables from dict
- */
- ListTablesReq * req = (ListTablesReq*)signal->getDataPtrSend();
- req->senderRef = reference();
- req->senderData = syncPtr.i;
- req->requestData = 0;
- /**
- * @todo: accomodate scan of index tables?
- */
- req->setTableType(DictTabInfo::UserTable);
-
- sendSignal(DBDICT_REF, GSN_LIST_TABLES_REQ, signal,
- ListTablesReq::SignalLength, JBB);
- break;
- }
- }
syncPtr.p->startMeta(signal);
break;
@@ -1209,16 +885,6 @@ SumaParticipant::sendSubSyncRef(Signal* signal, Uint32 errCode){
*/
void
-SumaParticipant::execLIST_TABLES_CONF(Signal* signal){
- jamEntry();
- CRASH_INSERTION(13005);
- ListTablesConf* const conf = (ListTablesConf*)signal->getDataPtr();
- SyncRecord* tmp = c_syncPool.getPtr(conf->senderData);
- tmp->runLIST_TABLES_CONF(signal);
-}
-
-
-void
SumaParticipant::execGET_TABINFOREF(Signal* signal){
jamEntry();
GetTabInfoRef* const ref = (GetTabInfoRef*)signal->getDataPtr();
@@ -1426,110 +1092,12 @@ SumaParticipant::execDIGETPRIMCONF(Signal* signal){
tmp->runDIGETPRIMCONF(signal);
}
-void
-SumaParticipant::execCREATE_TRIG_CONF(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION(13009);
-
- CreateTrigConf * const conf = (CreateTrigConf*)signal->getDataPtr();
-
- const Uint32 senderData = conf->getConnectionPtr();
- SyncRecord* tmp = c_syncPool.getPtr(senderData);
- tmp->runCREATE_TRIG_CONF(signal);
-
- /**
- * dodido
- * @todo: I (Johan) dont know what to do here. Jonas, what do you mean?
- */
-}
-
-void
-SumaParticipant::execCREATE_TRIG_REF(Signal* signal){
- jamEntry();
- ndbrequire(false);
-}
-
-void
-SumaParticipant::execDROP_TRIG_CONF(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION(13010);
-
- DropTrigConf * const conf = (DropTrigConf*)signal->getDataPtr();
-
- const Uint32 senderData = conf->getConnectionPtr();
- SyncRecord* tmp = c_syncPool.getPtr(senderData);
- tmp->runDROP_TRIG_CONF(signal);
-}
-
-void
-SumaParticipant::execDROP_TRIG_REF(Signal* signal){
- jamEntry();
-
- DropTrigRef * const ref = (DropTrigRef*)signal->getDataPtr();
-
- const Uint32 senderData = ref->getConnectionPtr();
- SyncRecord* tmp = c_syncPool.getPtr(senderData);
- tmp->runDROP_TRIG_CONF(signal);
-}
-
/*************************************************************************
*
*
*/
void
-SumaParticipant::SyncRecord::runLIST_TABLES_CONF(Signal* signal){
- jam();
-
- ListTablesConf * const conf = (ListTablesConf*)signal->getDataPtr();
- const Uint32 len = signal->length() - ListTablesConf::HeaderLength;
-
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
-
- for (unsigned i = 0; i < len; i++) {
- subPtr.p->m_maxTables++;
- suma.addTableId(ListTablesConf::getTableId(conf->tableData[i]), subPtr, this);
- }
-
- // for (unsigned i = 0; i < len; i++)
- // conf->tableData[i] = ListTablesConf::getTableId(conf->tableData[i]);
- // m_tableList.append(&conf->tableData[0], len);
-
-#if 0
- TableList::DataBufferIterator it;
- int i = 0;
- for(m_tableList.first(it);!it.isNull();m_tableList.next(it)) {
- ndbout_c("%u listtableconf tableid %d", i++, *it.data);
- }
-#endif
-
- if(len == ListTablesConf::DataLength){
- jam();
- // we expect more LIST_TABLE_CONF
- return;
- }
-
-#if 0
- subPtr.p->m_currentTable = 0;
- subPtr.p->m_maxTables = 0;
-
- TableList::DataBufferIterator it;
- for(m_tableList.first(it); !it.isNull(); m_tableList.next(it)) {
- subPtr.p->m_maxTables++;
- suma.addTableId(*it.data, subPtr, NULL);
-#ifdef NODEFAIL_DEBUG
- ndbout_c(" listtableconf tableid %d",*it.data);
-#endif
- }
-#endif
-
- startMeta(signal);
-}
-
-void
SumaParticipant::SyncRecord::startMeta(Signal* signal){
jam();
m_currentTable = 0;
@@ -1628,18 +1196,6 @@ SumaParticipant::SyncRecord::runGET_TABINFO_CONF(Signal* signal){
SegmentedSectionPtr ptr;
signal->getSection(ptr, GetTabInfoConf::DICT_TAB_INFO);
- SubMetaData * data = (SubMetaData*)signal->getDataPtrSend();
- /**
- * sending lastCompleteGCI. Used by Lars in interval calculations
- * incremenet by one, since last_CompleteGCI is the not the current gci.
- */
- data->gci = suma.c_lastCompleteGCI + 1;
- data->tableId = tableId;
- data->senderData = subPtr.p->m_subscriberData;
-#if PRINT_ONLY
- ndbout_c("GSN_SUB_META_DATA Table %d", tableId);
-#else
-
bool okToSend = m_doSendSyncData;
/*
@@ -1669,7 +1225,6 @@ SumaParticipant::SyncRecord::runGET_TABINFO_CONF(Signal* signal){
SubMetaData::SignalLength, JBB);
}
}
-#endif
TablePtr tabPtr;
ndbrequire(suma.c_tables.find(tabPtr, tableId));
@@ -2045,514 +1600,6 @@ SumaParticipant::execSCAN_HBREP(Signal* signal){
}
/**********************************************************
- *
- * Suma participant interface
- *
- * Creation of subscriber
- *
- */
-
-void
-SumaParticipant::execSUB_START_REQ(Signal* signal){
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_START_REQ");
-#endif
-
- CRASH_INSERTION(13013);
-
- if (c_restartLock) {
- jam();
- // ndbout_c("c_restartLock");
- if (RtoI(signal->getSendersBlockRef(), false) == RNIL) {
- jam();
- sendSubStartRef(signal, /** Error Code */ 0, true);
- return;
- }
- // only allow other Suma's in the nodegroup to come through for restart purposes
- }
-
- Subscription key;
-
- SubStartReq * const req = (SubStartReq*)signal->getDataPtr();
-
- Uint32 senderRef = req->senderRef;
- Uint32 senderData = req->senderData;
- Uint32 subscriberData = req->subscriberData;
- Uint32 subscriberRef = req->subscriberRef;
- SubscriptionData::Part part = (SubscriptionData::Part)req->part;
- key.m_subscriptionId = req->subscriptionId;
- key.m_subscriptionKey = req->subscriptionKey;
-
- SubscriptionPtr subPtr;
- if(!c_subscriptions.find(subPtr, key)){
- jam();
- sendSubStartRef(signal, /** Error Code */ 0);
- return;
- }
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
- if (syncPtr.p->m_locked) {
- jam();
-#if 0
- ndbout_c("Locked");
-#endif
- sendSubStartRef(signal, /** Error Code */ 0, true);
- return;
- }
- syncPtr.p->m_locked = true;
-
- SubscriberPtr subbPtr;
- if(!c_subscriberPool.seize(subbPtr)){
- jam();
- syncPtr.p->m_locked = false;
- sendSubStartRef(signal, /** Error Code */ 0);
- return;
- }
-
- Uint32 type = subPtr.p->m_subscriptionType;
-
- subbPtr.p->m_senderRef = senderRef;
- subbPtr.p->m_senderData = senderData;
-
- switch (type) {
- case SubCreateReq::TableEvent:
- jam();
- // we want the data to return to the API not DICT
- subbPtr.p->m_subscriberRef = subscriberRef;
- // ndbout_c("start ref = %u", signal->getSendersBlockRef());
- // ndbout_c("ref = %u", subbPtr.p->m_subscriberRef);
- // we use the subscription id for now, should really be API choice
- subbPtr.p->m_subscriberData = subscriberData;
-
-#if 0
- if (RtoI(signal->getSendersBlockRef(), false) == RNIL) {
- jam();
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- Uint32 ref = calcSumaBlockRef(c_nodesInGroup[i]);
- if (ref != reference()) {
- jam();
- sendSubStartReq(subPtr, subbPtr, signal, ref);
- } else
- jam();
- }
- }
-#endif
- break;
- case SubCreateReq::DatabaseSnapshot:
- case SubCreateReq::SelectiveTableSnapshot:
- jam();
- ndbrequire(false);
- //subbPtr.p->m_subscriberRef = GREP_REF;
- subbPtr.p->m_subscriberData = subPtr.p->m_subscriberData;
- break;
- case SubCreateReq::SingleTableScan:
- jam();
- subbPtr.p->m_subscriberRef = subPtr.p->m_subscriberRef;
- subbPtr.p->m_subscriberData = subPtr.p->m_subscriberData;
- }
-
- subbPtr.p->m_subPtrI = subPtr.i;
- subbPtr.p->m_firstGCI = RNIL;
- if (type == SubCreateReq::TableEvent)
- subbPtr.p->m_lastGCI = 0;
- else
- subbPtr.p->m_lastGCI = RNIL; // disable usage of m_lastGCI
- bool ok = false;
-
- switch(part){
- case SubscriptionData::MetaData:
- ok = true;
- jam();
- c_metaSubscribers.add(subbPtr);
- sendSubStartComplete(signal, subbPtr, 0, part);
- break;
- case SubscriptionData::TableData:
- ok = true;
- jam();
- c_prepDataSubscribers.add(subbPtr);
- syncPtr.p->startTrigger(signal);
- break;
- }
- ndbrequire(ok);
-}
-
-void
-SumaParticipant::sendSubStartComplete(Signal* signal,
- SubscriberPtr subbPtr,
- Uint32 firstGCI,
- SubscriptionData::Part part){
- jam();
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
- syncPtr.p->m_locked = false;
-
- SubStartConf * const conf = (SubStartConf*)signal->getDataPtrSend();
-
- conf->senderRef = reference();
- conf->senderData = subbPtr.p->m_senderData;
- conf->subscriptionId = subPtr.p->m_subscriptionId;
- conf->subscriptionKey = subPtr.p->m_subscriptionKey;
- conf->firstGCI = firstGCI;
- conf->part = (Uint32) part;
-
- conf->subscriberData = subPtr.p->m_subscriberData;
- sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_START_CONF, signal,
- SubStartConf::SignalLength, JBB);
-}
-
-#if 0
-void
-SumaParticipant::sendSubStartRef(SubscriptionPtr subPtr,
- Signal* signal, Uint32 errCode,
- bool temporary){
- jam();
- SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
- xxx ref->senderRef = reference();
- xxx ref->senderData = subPtr.p->m_senderData;
- ref->subscriptionId = subPtr.p->m_subscriptionId;
- ref->subscriptionKey = subPtr.p->m_subscriptionKey;
- ref->part = (Uint32) subPtr.p->m_subscriptionType;
- ref->subscriberData = subPtr.p->m_subscriberData;
- ref->err = errCode;
- if (temporary) {
- jam();
- ref->setTemporary();
- }
- releaseSections(signal);
- sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_START_REF, signal,
- SubStartRef::SignalLength, JBB);
-}
-#endif
-void
-SumaParticipant::sendSubStartRef(Signal* signal, Uint32 errCode,
- bool temporary){
- jam();
- SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->err = errCode;
- if (temporary) {
- jam();
- ref->setTemporary();
- }
- releaseSections(signal);
- sendSignal(signal->getSendersBlockRef(), GSN_SUB_START_REF, signal,
- SubStartRef::SignalLength, JBB);
-}
-
-/**********************************************************
- *
- * Trigger admin interface
- *
- */
-
-void
-SumaParticipant::SyncRecord::startTrigger(Signal* signal){
- jam();
- m_currentTable = 0;
- m_latestTriggerId = RNIL;
- nextTrigger(signal);
-}
-
-void
-SumaParticipant::SyncRecord::nextTrigger(Signal* signal){
- jam();
-
- TableList::DataBufferIterator it;
-
- if(!m_tableList.position(it, m_currentTable)){
- completeTrigger(signal);
- return;
- }
-
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
- ndbrequire(subPtr.p->m_syncPtrI == ptrI);
- const Uint32 RT_BREAK = 48;
- Uint32 latestTriggerId = 0;
- for(Uint32 i = 0; i<RT_BREAK && !it.isNull(); i++, m_tableList.next(it)){
- TablePtr tabPtr;
-#if 0
- ndbout_c("nextTrigger tableid %u", *it.data);
-#endif
- ndbrequire(suma.c_tables.find(tabPtr, *it.data));
-
- AttributeMask attrMask;
- createAttributeMask(attrMask, tabPtr.p);
-
- for(Uint32 j = 0; j<3; j++){
- i++;
- latestTriggerId = (tabPtr.p->m_schemaVersion << 18) |
- (j << 16) | tabPtr.p->m_tableId;
- if(tabPtr.p->m_hasTriggerDefined[j] == 0) {
- ndbrequire(tabPtr.p->m_triggerIds[j] == ILLEGAL_TRIGGER_ID);
-#if 0
- ndbout_c("DEFINING trigger on table %u[%u]", tabPtr.p->m_tableId, j);
-#endif
- CreateTrigReq * const req = (CreateTrigReq*)signal->getDataPtrSend();
- req->setUserRef(SUMA_REF);
- req->setConnectionPtr(ptrI);
- req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE);
- req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
- req->setMonitorReplicas(true);
- req->setMonitorAllAttributes(false);
- req->setReceiverRef(SUMA_REF);
- req->setTriggerId(latestTriggerId);
- req->setTriggerEvent((TriggerEvent::Value)j);
- req->setTableId(tabPtr.p->m_tableId);
- req->setAttributeMask(attrMask);
- suma.sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ,
- signal, CreateTrigReq::SignalLength, JBB);
-
- } else {
- /**
- * Faking that a trigger has been created in order to
- * simulate the proper behaviour.
- * Perhaps this should be a dummy signal instead of
- * (ab)using CREATE_TRIG_CONF.
- */
- CreateTrigConf * conf = (CreateTrigConf*)signal->getDataPtrSend();
- conf->setConnectionPtr(ptrI);
- conf->setTableId(tabPtr.p->m_tableId);
- conf->setTriggerId(latestTriggerId);
- suma.sendSignal(SUMA_REF,GSN_CREATE_TRIG_CONF,
- signal, CreateTrigConf::SignalLength, JBB);
-
- }
-
- }
- m_currentTable++;
- }
- m_latestTriggerId = latestTriggerId;
-}
-
-void
-SumaParticipant::SyncRecord::createAttributeMask(AttributeMask& mask,
- Table * table){
- jam();
- mask.clear();
- DataBuffer<15>::DataBufferIterator it;
- LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, table->m_attributes);
- for(attrBuf.first(it); !it.curr.isNull(); attrBuf.next(it)){
- mask.set(* it.data);
- }
-}
-
-void
-SumaParticipant::SyncRecord::runCREATE_TRIG_CONF(Signal* signal){
- jam();
-
- CreateTrigConf * const conf = (CreateTrigConf*)signal->getDataPtr();
- const Uint32 triggerId = conf->getTriggerId();
- Uint32 type = (triggerId >> 16) & 0x3;
- Uint32 tableId = conf->getTableId();
-
- TablePtr tabPtr;
- ndbrequire(suma.c_tables.find(tabPtr, tableId));
-
- ndbrequire(type < 3);
- tabPtr.p->m_triggerIds[type] = triggerId;
- tabPtr.p->m_hasTriggerDefined[type]++;
-
- if(triggerId == m_latestTriggerId){
- jam();
- nextTrigger(signal);
- }
-}
-
-void
-SumaParticipant::SyncRecord::completeTrigger(Signal* signal){
- jam();
- SubscriptionPtr subPtr;
- CRASH_INSERTION(13013);
-#ifdef EVENT_PH3_DEBUG
- ndbout_c("SumaParticipant: trigger completed");
-#endif
- Uint32 gci;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
- ndbrequire(subPtr.p->m_syncPtrI == ptrI);
-
- SubscriberPtr subbPtr;
- {
- bool found = false;
-
- for(suma.c_prepDataSubscribers.first(subbPtr);
- !subbPtr.isNull(); suma.c_prepDataSubscribers.next(subbPtr)) {
- jam();
- if(subbPtr.p->m_subPtrI == subPtr.i) {
- jam();
- found = true;
- break;
- }
- }
- ndbrequire(found);
- gci = suma.getFirstGCI(signal);
- subbPtr.p->m_firstGCI = gci;
- suma.c_prepDataSubscribers.remove(subbPtr);
- suma.c_dataSubscribers.add(subbPtr);
- }
- suma.sendSubStartComplete(signal, subbPtr, gci, SubscriptionData::TableData);
-}
-
-void
-SumaParticipant::SyncRecord::startDropTrigger(Signal* signal){
- jam();
- m_currentTable = 0;
- m_latestTriggerId = RNIL;
- nextDropTrigger(signal);
-}
-
-void
-SumaParticipant::SyncRecord::nextDropTrigger(Signal* signal){
- jam();
-
- TableList::DataBufferIterator it;
-
- if(!m_tableList.position(it, m_currentTable)){
- completeDropTrigger(signal);
- return;
- }
-
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
- ndbrequire(subPtr.p->m_syncPtrI == ptrI);
-
- const Uint32 RT_BREAK = 48;
- Uint32 latestTriggerId = 0;
- for(Uint32 i = 0; i<RT_BREAK && !it.isNull(); i++, m_tableList.next(it)){
- jam();
- TablePtr tabPtr;
-#if 0
- ndbout_c("nextDropTrigger tableid %u", *it.data);
-#endif
- ndbrequire(suma.c_tables.find(tabPtr, * it.data));
-
- for(Uint32 j = 0; j<3; j++){
- jam();
- ndbrequire(tabPtr.p->m_triggerIds[j] != ILLEGAL_TRIGGER_ID);
- i++;
- latestTriggerId = tabPtr.p->m_triggerIds[j];
- if(tabPtr.p->m_hasTriggerDefined[j] == 1) {
- jam();
-
- DropTrigReq * const req = (DropTrigReq*)signal->getDataPtrSend();
- req->setConnectionPtr(ptrI);
- req->setUserRef(SUMA_REF); // Sending to myself
- req->setRequestType(DropTrigReq::RT_USER);
- req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE);
- req->setTriggerActionTime(TriggerActionTime::TA_DETACHED);
- req->setIndexId(RNIL);
-
- req->setTableId(tabPtr.p->m_tableId);
- req->setTriggerId(latestTriggerId);
- req->setTriggerEvent((TriggerEvent::Value)j);
-
-#if 0
- ndbout_c("DROPPING trigger %u = %u %u %u on table %u[%u]",
- latestTriggerId,TriggerType::SUBSCRIPTION_BEFORE,
- TriggerActionTime::TA_DETACHED, j, tabPtr.p->m_tableId, j);
-#endif
- suma.sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ,
- signal, DropTrigReq::SignalLength, JBB);
- } else {
- jam();
- ndbrequire(tabPtr.p->m_hasTriggerDefined[j] > 1);
- /**
- * Faking that a trigger has been dropped in order to
- * simulate the proper behaviour.
- * Perhaps this should be a dummy signal instead of
- * (ab)using DROP_TRIG_CONF.
- */
- DropTrigConf * conf = (DropTrigConf*)signal->getDataPtrSend();
- conf->setConnectionPtr(ptrI);
- conf->setTableId(tabPtr.p->m_tableId);
- conf->setTriggerId(latestTriggerId);
- suma.sendSignal(SUMA_REF,GSN_DROP_TRIG_CONF,
- signal, DropTrigConf::SignalLength, JBB);
- }
- }
- m_currentTable++;
- }
- m_latestTriggerId = latestTriggerId;
-}
-
-void
-SumaParticipant::SyncRecord::runDROP_TRIG_REF(Signal* signal){
- jam();
- DropTrigRef * const ref = (DropTrigRef*)signal->getDataPtr();
- if (ref->getErrorCode() != DropTrigRef::TriggerNotFound){
- ndbrequire(false);
- }
- const Uint32 triggerId = ref->getTriggerId();
- Uint32 tableId = ref->getTableId();
- runDropTrig(signal, triggerId, tableId);
-}
-
-void
-SumaParticipant::SyncRecord::runDROP_TRIG_CONF(Signal* signal){
- jam();
-
- DropTrigConf * const conf = (DropTrigConf*)signal->getDataPtr();
- const Uint32 triggerId = conf->getTriggerId();
- Uint32 tableId = conf->getTableId();
- runDropTrig(signal, triggerId, tableId);
-}
-
-void
-SumaParticipant::SyncRecord::runDropTrig(Signal* signal,
- Uint32 triggerId,
- Uint32 tableId){
- Uint32 type = (triggerId >> 16) & 0x3;
-
- TablePtr tabPtr;
- ndbrequire(suma.c_tables.find(tabPtr, tableId));
-
- ndbrequire(type < 3);
- ndbrequire(tabPtr.p->m_triggerIds[type] == triggerId);
- tabPtr.p->m_hasTriggerDefined[type]--;
- if (tabPtr.p->m_hasTriggerDefined[type] == 0) {
- jam();
- tabPtr.p->m_triggerIds[type] = ILLEGAL_TRIGGER_ID;
- }
- if(triggerId == m_latestTriggerId){
- jam();
- nextDropTrigger(signal);
- }
-}
-
-void
-SumaParticipant::SyncRecord::completeDropTrigger(Signal* signal){
- jam();
- SubscriptionPtr subPtr;
- CRASH_INSERTION(13014);
-#if 0
- ndbout_c("trigger completed");
-#endif
-
- suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI);
- ndbrequire(subPtr.p->m_syncPtrI == ptrI);
-
- bool found = false;
- SubscriberPtr subbPtr;
- for(suma.c_prepDataSubscribers.first(subbPtr);
- !subbPtr.isNull(); suma.c_prepDataSubscribers.next(subbPtr)) {
- jam();
- if(subbPtr.p->m_subPtrI == subPtr.i) {
- jam();
- found = true;
- break;
- }
- }
- ndbrequire(found);
- suma.sendSubStopComplete(signal, subbPtr);
-}
-
-/**********************************************************
* Scan data interface
*
* Assumption: one execTRANSID_AI contains all attr info
@@ -2645,705 +1692,6 @@ SumaParticipant::execTRANSID_AI(Signal* signal){
f_bufferLock = 0;
}
-/**********************************************************
- *
- * Trigger data interface
- *
- */
-
-void
-SumaParticipant::execTRIG_ATTRINFO(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION(13016);
- TrigAttrInfo* const trg = (TrigAttrInfo*)signal->getDataPtr();
- const Uint32 trigId = trg->getTriggerId();
-
- const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength;
-
- if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES){
- jam();
-
- ndbrequire(b_bufferLock == trigId);
-
- memcpy(b_buffer + b_trigBufferSize, trg->getData(), 4 * dataLen);
- b_trigBufferSize += dataLen;
- // printf("before values %u %u %u\n",trigId, dataLen, b_trigBufferSize);
- } else {
- jam();
-
- if(f_bufferLock == 0){
- f_bufferLock = trigId;
- f_trigBufferSize = 0;
- b_bufferLock = trigId;
- b_trigBufferSize = 0;
- } else {
- ndbrequire(f_bufferLock == trigId);
- }
-
- memcpy(f_buffer + f_trigBufferSize, trg->getData(), 4 * dataLen);
- f_trigBufferSize += dataLen;
- }
-}
-
-#ifdef NODEFAIL_DEBUG2
-static int theCounts[64] = {0};
-#endif
-
-Uint32
-Suma::getStoreBucket(Uint32 v)
-{
- // id will contain id to responsible suma or
- // RNIL if we don't have nodegroup info yet
-
- const Uint32 N = NO_OF_BUCKETS;
- const Uint32 D = v % N; // Distibution key
- return D;
-}
-
-Uint32
-Suma::getResponsibleSumaNodeId(Uint32 D)
-{
- // id will contain id to responsible suma or
- // RNIL if we don't have nodegroup info yet
-
- Uint32 id;
-
- if (c_restartLock) {
- jam();
- // ndbout_c("c_restartLock");
- id = RNIL;
- } else {
- jam();
- id = RNIL;
- const Uint32 n = c_noNodesInGroup; // Number nodes in node group
- const Uint32 C1 = D / n;
- const Uint32 C2 = D - C1*n; // = D % n;
- const Uint32 C = C2 + C1 % n;
- for (Uint32 i = 0; i < n; i++) {
- jam();
- id = c_nodesInGroup[(C + i) % n];
- if (c_aliveNodes.get(id) &&
- !c_preparingNodes.get(id)) {
- jam();
- break;
- }//if
- }
-#ifdef NODEFAIL_DEBUG2
- theCounts[id]++;
- ndbout_c("Suma:responsible n=%u, D=%u, id = %u, count=%u",
- n,D, id, theCounts[id]);
-#endif
- }
- return id;
-}
-
-Uint32
-SumaParticipant::decideWhoToSend(Uint32 nBucket, Uint32 gci){
- bool replicaFlag = true;
- Uint32 nId = RNIL;
-
- // bucket active/not active set by GCP_COMPLETE
- if (c_buckets[nBucket].active) {
- if (c_buckets[nBucket].handover && c_buckets[nBucket].handoverGCI <= gci) {
- jam();
- replicaFlag = true; // let the other node send this
- nId = RNIL;
- // mark this as started, if we get a node failiure now we have some lost stuff
- c_buckets[nBucket].handover_started = true;
- } else {
- jam();
- replicaFlag = false;
- nId = refToNode(reference());
- }
- } else {
- nId = getResponsibleSumaNodeId(nBucket);
- replicaFlag = !(nId == refToNode(reference()));
-
- if (!replicaFlag) {
- if (!c_buckets[nBucket].handover) {
- jam();
- // appearently a node has failed and we are taking over sending
- // from that bucket. Now we need to go back to latest completed
- // GCI. Handling will depend on Subscriber and Subscription
-
- // TODO, for now we make an easy takeover
- if (gci < c_nodeFailGCI)
- c_lastInconsistentGCI = gci;
-
- // we now have responsability for this bucket and we're actively
- // sending from that
- c_buckets[nBucket].active = true;
-#ifdef HANDOVER_DEBUG
- ndbout_c("Takeover Bucket %u", nBucket);
-#endif
- } else if (c_buckets[nBucket].handoverGCI > gci) {
- jam();
- replicaFlag = true; // handover going on, but don't start sending yet
- nId = RNIL;
- } else {
- jam();
-#ifdef HANDOVER_DEBUG
- ndbout_c("Possible error: Will send from GCI = %u", gci);
-#endif
- }
- }
- }
-
-#ifdef NODEFAIL_DEBUG2
- ndbout_c("Suma:bucket %u, responsible id = %u, replicaFlag = %u",
- nBucket, nId, (Uint32)replicaFlag);
-#endif
- return replicaFlag;
-}
-
-void
-SumaParticipant::execFIRE_TRIG_ORD(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION(13016);
- FireTrigOrd* const trg = (FireTrigOrd*)signal->getDataPtr();
- const Uint32 trigId = trg->getTriggerId();
- const Uint32 hashValue = trg->getHashValue();
- const Uint32 gci = trg->getGCI();
- const Uint32 event = trg->getTriggerEvent();
- const Uint32 triggerId = trg->getTriggerId();
- Uint32 tableId = triggerId & 0xFFFF;
-
- ndbrequire(f_bufferLock == trigId);
-
-#ifdef EVENT_DEBUG2
- ndbout_c("SumaParticipant::execFIRE_TRIG_ORD");
-#endif
-
- Uint32 sz = trg->getNoOfPrimaryKeyWords()+trg->getNoOfAfterValueWords();
- ndbrequire(sz == f_trigBufferSize);
-
- /**
- * Reformat as "all headers" + "all data"
- */
- Uint32 dataLen = 0;
- Uint32 noOfAttrs = 0;
- Uint32 * src = f_buffer;
- Uint32 * headers = signal->theData + 25;
- Uint32 * dst = signal->theData + 25 + MAX_ATTRIBUTES_IN_TABLE;
-
- LinearSectionPtr ptr[3];
- int nptr;
-
- ptr[0].p = headers;
- ptr[1].p = dst;
-
- while(sz > 0){
- jam();
- Uint32 tmp = * src ++;
- * headers ++ = tmp;
- Uint32 len = AttributeHeader::getDataSize(tmp);
- memcpy(dst, src, 4 * len);
- dst += len;
- src += len;
-
- noOfAttrs++;
- dataLen += len;
- sz -= (1 + len);
- }
- ndbrequire(sz == 0);
-
- ptr[0].sz = noOfAttrs;
- ptr[1].sz = dataLen;
-
- if (b_trigBufferSize > 0) {
- jam();
- ptr[2].p = b_buffer;
- ptr[2].sz = b_trigBufferSize;
- nptr = 3;
- } else {
- jam();
- nptr = 2;
- }
-
- // right now only for tableEvent
- bool replicaFlag = decideWhoToSend(getStoreBucket(hashValue), gci);
-
- /**
- * Signal to subscriber(s)
- */
- SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg;
- data->gci = gci;
- data->tableId = tableId;
- data->operation = event;
- data->noOfAttributes = noOfAttrs;
- data->dataSize = dataLen;
-
- SubscriberPtr subbPtr;
- for(c_dataSubscribers.first(subbPtr); !subbPtr.isNull();
- c_dataSubscribers.next(subbPtr)){
- if (subbPtr.p->m_firstGCI > gci) {
-#ifdef EVENT_DEBUG
- ndbout_c("m_firstGCI = %u, gci = %u", subbPtr.p->m_firstGCI, gci);
-#endif
- jam();
- // we're either restarting or it's a newly created subscriber
- // and waiting for the right gci
- continue;
- }
-
- jam();
-
- const Uint32 ref = subbPtr.p->m_subscriberRef;
- // ndbout_c("ref = %u", ref);
- const Uint32 subdata = subbPtr.p->m_subscriberData;
- data->senderData = subdata;
- /*
- * get subscription ptr for this subscriber
- */
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-
- if(!subPtr.p->m_tables[tableId]) {
- jam();
- continue;
- //continue in for-loop if the table is not part of
- //the subscription. Otherwise, send data to subscriber.
- }
-
- if (subPtr.p->m_subscriptionType == SubCreateReq::TableEvent) {
- if (replicaFlag) {
- jam();
- c_failoverBuffer.subTableData(gci,NULL,0);
- continue;
- }
- jam();
- Uint32 tmp = data->logType;
- if (c_lastInconsistentGCI == data->gci) {
- data->setGCINotConsistent();
- }
-
-#ifdef HANDOVER_DEBUG
- {
- static int aLongGCIName = 0;
- if (data->gci != aLongGCIName) {
- aLongGCIName = data->gci;
- ndbout_c("sent from GCI = %u", aLongGCIName);
- }
- }
-#endif
- sendSignal(ref, GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength, JBB, ptr, nptr);
- data->logType = tmp;
- } else {
- ndbassert(refToNode(ref) == 0 || refToNode(ref) == getOwnNodeId());
- jam();
-#if PRINT_ONLY
- ndbout_c("GSN_SUB_TABLE_DATA to %s: op: %d #attr: %d len: %d",
- getBlockName(refToBlock(ref)),
- noOfAttrs, dataLen);
-
-#else
-#ifdef HANDOVER_DEBUG
- {
- static int aLongGCIName2 = 0;
- if (data->gci != aLongGCIName2) {
- aLongGCIName2 = data->gci;
- ndbout_c("(EXECUTE_DIRECT) sent from GCI = %u to %u", aLongGCIName2, ref);
- }
- }
-#endif
- EXECUTE_DIRECT(refToBlock(ref), GSN_SUB_TABLE_DATA, signal,
- SubTableData::SignalLength);
- jamEntry();
-#endif
- }
- }
-
- /**
- * Reset f_bufferLock
- */
- f_bufferLock = 0;
- b_bufferLock = 0;
-}
-
-void
-SumaParticipant::execSUB_GCP_COMPLETE_REP(Signal* signal){
- jamEntry();
-
- SubGcpCompleteRep * rep = (SubGcpCompleteRep*)signal->getDataPtrSend();
-
- Uint32 gci = rep->gci;
- c_lastCompleteGCI = gci;
-
- /**
- * Signal to subscriber(s)
- */
-
- SubscriberPtr subbPtr;
- SubscriptionPtr subPtr;
- c_dataSubscribers.first(subbPtr);
- for(; !subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){
-
- if (subbPtr.p->m_firstGCI > gci) {
- jam();
- // we don't send SUB_GCP_COMPLETE_REP for incomplete GCI's
- continue;
- }
-
- const Uint32 ref = subbPtr.p->m_subscriberRef;
- rep->senderRef = ref;
- rep->senderData = subbPtr.p->m_subscriberData;
-
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-#if PRINT_ONLY
- ndbout_c("GSN_SUB_GCP_COMPLETE_REP to %s:",
- getBlockName(refToBlock(ref)));
-#else
-
- CRASH_INSERTION(13018);
-
- if (subPtr.p->m_subscriptionType == SubCreateReq::TableEvent)
- {
- jam();
- sendSignal(ref, GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength, JBB);
- }
- else
- {
- jam();
- ndbassert(refToNode(ref) == 0 || refToNode(ref) == getOwnNodeId());
- EXECUTE_DIRECT(refToBlock(ref), GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength);
- jamEntry();
- }
-#endif
- }
-
- if (c_handoverToDo) {
- jam();
- c_handoverToDo = false;
- for( int i = 0; i < NO_OF_BUCKETS; i++) {
- if (c_buckets[i].handover) {
- if (c_buckets[i].handoverGCI > gci) {
- jam();
- c_handoverToDo = true; // still waiting for the right GCI
- break; /* since all handover should happen at the same time
- * we can break here
- */
- } else {
- c_buckets[i].handover = false;
-#ifdef HANDOVER_DEBUG
- ndbout_c("Handover Bucket %u", i);
-#endif
- if (getResponsibleSumaNodeId(i) == refToNode(reference())) {
- // my bucket to be handed over to me
- ndbrequire(!c_buckets[i].active);
- jam();
- c_buckets[i].active = true;
- } else {
- // someone else's bucket to handover to
- ndbrequire(c_buckets[i].active);
- jam();
- c_buckets[i].active = false;
- }
- }
- }
- }
- }
-}
-
-/***********************************************************
- *
- * Embryo to syncronize the Suma's so as to know if a subscriber
- * has received a GCP_COMPLETE from all suma's or not
- *
- */
-
-void
-SumaParticipant::runSUB_GCP_COMPLETE_ACC(Signal* signal){
- jam();
-
- SubGcpCompleteAcc * const acc = (SubGcpCompleteAcc*)signal->getDataPtr();
-
- Uint32 gci = acc->rep.gci;
-
-#ifdef EVENT_DEBUG
- ndbout_c("SumaParticipant::runSUB_GCP_COMPLETE_ACC gci = %u", gci);
-#endif
-
- c_failoverBuffer.subGcpCompleteRep(gci);
-}
-
-void
-Suma::execSUB_GCP_COMPLETE_ACC(Signal* signal){
- jamEntry();
-
- if (RtoI(signal->getSendersBlockRef(), false) != RNIL) {
- jam();
- // Ack from other SUMA
- runSUB_GCP_COMPLETE_ACC(signal);
- return;
- }
-
- jam();
- // Ack from User and not an acc from other SUMA, redistribute in nodegroup
-
- SubGcpCompleteAcc * const acc = (SubGcpCompleteAcc*)signal->getDataPtr();
- Uint32 gci = acc->rep.gci;
- Uint32 senderRef = acc->rep.senderRef;
- Uint32 subscriberData = acc->rep.subscriberData;
-
-#ifdef EVENT_DEBUG
- ndbout_c("Suma::execSUB_GCP_COMPLETE_ACC gci = %u", gci);
-#endif
- bool moreToCome = false;
-
- SubscriberPtr subbPtr;
- for(c_dataSubscribers.first(subbPtr);
- !subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){
-#ifdef EVENT_DEBUG
- ndbout_c("Suma::execSUB_GCP_COMPLETE_ACC %u == %u && %u == %u",
- subbPtr.p->m_subscriberRef,
- senderRef,
- subbPtr.p->m_subscriberData,
- subscriberData);
-#endif
- if (subbPtr.p->m_subscriberRef == senderRef &&
- subbPtr.p->m_subscriberData == subscriberData) {
- jam();
-#ifdef EVENT_DEBUG
- ndbout_c("Suma::execSUB_GCP_COMPLETE_ACC gci = FOUND SUBSCRIBER");
-#endif
- subbPtr.p->m_lastGCI = gci;
- } else if (subbPtr.p->m_lastGCI < gci) {
- jam();
- if (subbPtr.p->m_firstGCI <= gci)
- moreToCome = true;
- } else
- jam();
- }
-
- if (!moreToCome) {
- // tell the other SUMA's that I'm done with this GCI
- jam();
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- Uint32 id = c_nodesInGroup[i];
- Uint32 ref = calcSumaBlockRef(id);
- if ((ref != reference()) && c_aliveNodes.get(id)) {
- jam();
- sendSignal(ref, GSN_SUB_GCP_COMPLETE_ACC, signal,
- SubGcpCompleteAcc::SignalLength, JBB);
- } else
- jam();
- }
- }
-}
-
-static Uint32 tmpFailoverBuffer[512];
-//SumaParticipant::FailoverBuffer::FailoverBuffer(DataBuffer<15>::DataBufferPool & p)
-// : m_dataList(p),
-SumaParticipant::FailoverBuffer::FailoverBuffer()
- :
- c_gcis(tmpFailoverBuffer), c_sz(512), c_first(0), c_next(0), c_full(false)
-{
-}
-
-bool SumaParticipant::FailoverBuffer::subTableData(Uint32 gci, Uint32 *src, int sz)
-{
- bool ok = true;
-
- if (c_full) {
- ok = false;
-#ifdef EVENT_DEBUG
- ndbout_c("Suma::FailoverBuffer::SubTableData buffer full gci=%u");
-#endif
- } else {
- c_gcis[c_next] = gci;
- c_next++;
- if (c_next == c_sz) c_next = 0;
- if (c_next == c_first)
- c_full = true;
- // ndbout_c("%u %u %u",c_first,c_next,c_sz);
- }
- return ok;
-}
-bool SumaParticipant::FailoverBuffer::subGcpCompleteRep(Uint32 gci)
-{
- bool ok = true;
-
- // ndbout_c("Empty");
- while (true) {
- if (c_first == c_next && !c_full)
- break;
- if (c_gcis[c_first] > gci)
- break;
- c_full = false;
- c_first++;
- if (c_first == c_sz) c_first = 0;
- // ndbout_c("%u %u %u : ",c_first,c_next,c_sz);
- }
-
- return ok;
-}
-bool SumaParticipant::FailoverBuffer::nodeFailRep()
-{
- bool ok = true;
- while (true) {
- if (c_first == c_next && !c_full)
- break;
-
-#ifdef EVENT_DEBUG
- ndbout_c("Suma::FailoverBuffer::NodeFailRep resending gci=%u", c_gcis[c_first]);
-#endif
- c_full = false;
- c_first++;
- if (c_first == c_sz) c_first = 0;
- }
- return ok;
-}
-
-/**********************************************************
- * Suma participant interface
- *
- * Stopping and removing of subscriber
- *
- */
-
-void
-SumaParticipant::execSUB_STOP_REQ(Signal* signal){
- jamEntry();
-
- CRASH_INSERTION(13019);
-
- SubStopReq * const req = (SubStopReq*)signal->getDataPtr();
- Uint32 senderRef = signal->getSendersBlockRef();
- Uint32 senderData = req->senderData;
- Uint32 subscriberRef = req->subscriberRef;
- Uint32 subscriberData = req->subscriberData;
- SubscriptionPtr subPtr;
- Subscription key;
- key.m_subscriptionId = req->subscriptionId;
- key.m_subscriptionKey = req->subscriptionKey;
- Uint32 part = req->part;
-
- if (key.m_subscriptionKey == 0 &&
- key.m_subscriptionId == 0 &&
- subscriberData == 0) {
- SubStopConf* conf = (SubStopConf*)signal->getDataPtrSend();
-
- conf->senderRef = reference();
- conf->senderData = senderData;
- conf->subscriptionId = key.m_subscriptionId;
- conf->subscriptionKey = key.m_subscriptionKey;
- conf->subscriberData = subscriberData;
-
- sendSignal(senderRef, GSN_SUB_STOP_CONF, signal,
- SubStopConf::SignalLength, JBB);
-
- removeSubscribersOnNode(signal, refToNode(subscriberRef));
- return;
- }
-
- if(!c_subscriptions.find(subPtr, key)){
- jam();
- sendSubStopRef(signal, GrepError::SUBSCRIPTION_ID_NOT_FOUND);
- return;
- }
-
- ndbrequire(part == SubscriptionData::TableData);
-
- SubscriberPtr subbPtr;
- if (senderRef == reference()){
- jam();
- c_subscriberPool.getPtr(subbPtr, senderData);
- ndbrequire(subbPtr.p->m_subPtrI == subPtr.i &&
- subbPtr.p->m_subscriberRef == subscriberRef &&
- subbPtr.p->m_subscriberData == subscriberData);
- c_removeDataSubscribers.remove(subbPtr);
- } else {
- bool found = false;
- jam();
- c_dataSubscribers.first(subbPtr);
- for (;!subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){
- jam();
- if (subbPtr.p->m_subPtrI == subPtr.i &&
- subbPtr.p->m_subscriberRef == subscriberRef &&
- subbPtr.p->m_subscriberData == subscriberData){
- // ndbout_c("STOP_REQ: before c_dataSubscribers.release");
- jam();
- c_dataSubscribers.remove(subbPtr);
- found = true;
- break;
- }
- }
- /**
- * If we didn't find anyone, send ref
- */
- if (!found) {
- jam();
- sendSubStopRef(signal, GrepError::SUBSCRIBER_NOT_FOUND);
- return;
- }
- }
-
- subbPtr.p->m_senderRef = senderRef; // store ref to requestor
- subbPtr.p->m_senderData = senderData; // store ref to requestor
- c_prepDataSubscribers.add(subbPtr);
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
- if (syncPtr.p->m_locked) {
- jam();
- sendSubStopRef(signal, /** Error Code */ 0, true);
- return;
- }
- syncPtr.p->m_locked = true;
-
- syncPtr.p->startDropTrigger(signal);
-}
-
-void
-SumaParticipant::sendSubStopComplete(Signal* signal, SubscriberPtr subbPtr){
- jam();
-
- CRASH_INSERTION(13020);
-
- SubscriptionPtr subPtr;
- c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
-
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
- syncPtr.p->m_locked = false;
-
- SubStopConf * const conf = (SubStopConf*)signal->getDataPtrSend();
-
- conf->senderRef = reference();
- conf->senderData = subbPtr.p->m_senderData;
- conf->subscriptionId = subPtr.p->m_subscriptionId;
- conf->subscriptionKey = subPtr.p->m_subscriptionKey;
- conf->subscriberData = subbPtr.p->m_subscriberData;
- Uint32 senderRef = subbPtr.p->m_senderRef;
-
- c_prepDataSubscribers.release(subbPtr);
- sendSignal(senderRef, GSN_SUB_STOP_CONF, signal,
- SubStopConf::SignalLength, JBB);
-}
-
-void
-SumaParticipant::sendSubStopRef(Signal* signal, Uint32 errCode,
- bool temporary){
- jam();
- SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
- ref->senderRef = reference();
- ref->errorCode = errCode;
- if (temporary) {
- ref->setTemporary();
- }
- sendSignal(signal->getSendersBlockRef(),
- GSN_SUB_STOP_REF,
- signal,
- SubStopRef::SignalLength,
- JBB);
- return;
-}
-
/**************************************************************
*
* Removing subscription
@@ -3374,36 +1722,6 @@ SumaParticipant::execSUB_REMOVE_REQ(Signal* signal) {
{
jam();
SubscriberPtr i_subbPtr;
- for(c_prepDataSubscribers.first(i_subbPtr);
- !i_subbPtr.isNull(); c_prepDataSubscribers.next(i_subbPtr)){
- jam();
- if( i_subbPtr.p->m_subPtrI == subPtr.i ) {
- jam();
- sendSubRemoveRef(signal, req, /* ErrorCode */ 0, true);
- return;
- // c_prepDataSubscribers.release(subbPtr);
- }
- }
- c_dataSubscribers.first(i_subbPtr);
- while(!i_subbPtr.isNull()){
- jam();
- SubscriberPtr subbPtr = i_subbPtr;
- c_dataSubscribers.next(i_subbPtr);
- if( subbPtr.p->m_subPtrI == subPtr.i ) {
- jam();
- sendSubRemoveRef(signal, req, /* ErrorCode */ 0, true);
- return;
- /* Unfinished/untested code. If remove should be possible
- * even if subscribers are left these have to be stopped
- * first. See m_markRemove, m_nSubscribers. We need also to
- * block remove for this subscription so that multiple
- * removes is not possible...
- */
- c_dataSubscribers.remove(subbPtr);
- c_removeDataSubscribers.add(subbPtr);
- count++;
- }
- }
c_metaSubscribers.first(i_subbPtr);
while(!i_subbPtr.isNull()){
jam();
@@ -3419,15 +1737,7 @@ SumaParticipant::execSUB_REMOVE_REQ(Signal* signal) {
subPtr.p->m_senderRef = senderRef;
subPtr.p->m_senderData = req.senderData;
- if (count > 0){
- jam();
- ndbrequire(false); // code not finalized
- subPtr.p->m_markRemove = true;
- subPtr.p->m_nSubscribers = count;
- sendSubStopReq(signal);
- } else {
- completeSubRemoveReq(signal, subPtr);
- }
+ completeSubRemoveReq(signal, subPtr);
}
void
@@ -3492,6 +1802,8 @@ SumaParticipant::sendSubRemoveRef(Signal* signal, const SubRemoveReq& req,
jam();
SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
ref->senderRef = reference();
+ ref->subscriptionId = req.subscriptionId;
+ ref->subscriptionKey = req.subscriptionKey;
ref->senderData = req.senderData;
ref->err = errCode;
if (temporary)
@@ -3522,486 +1834,5 @@ SumaParticipant::SyncRecord::release(){
attrBuf.release();
}
-
-/**************************************************************
- *
- * Restarting remote node functions, master functionality
- * (slave does nothing special)
- * - triggered on INCL_NODEREQ calling startNode
- * - included node will issue START_ME when it's ready to start
- * the subscribers
- *
- */
-
-Suma::Restart::Restart(Suma& s) : suma(s) {
- for (int i = 0; i < MAX_REPLICAS; i++) {
- c_okToStart[i] = false;
- c_waitingToStart[i] = false;
- }
-}
-
-void
-Suma::Restart::resetNode(Uint32 sumaRef)
-{
- jam();
- int I = suma.RtoI(sumaRef);
- c_okToStart[I] = false;
- c_waitingToStart[I] = false;
-}
-
-void
-Suma::Restart::startNode(Signal* signal, Uint32 sumaRef)
-{
- jam();
- resetNode(sumaRef);
-
- // right now we can only handle restarting one node
- // at a time in a node group
-
- createSubscription(signal, sumaRef);
-}
-
-void
-Suma::Restart::createSubscription(Signal* signal, Uint32 sumaRef) {
- jam();
- suma.c_subscriptions.first(c_subPtr);
- nextSubscription(signal, sumaRef);
-}
-
-void
-Suma::Restart::nextSubscription(Signal* signal, Uint32 sumaRef) {
- jam();
- if (c_subPtr.isNull()) {
- jam();
- completeSubscription(signal, sumaRef);
- return;
- }
- SubscriptionPtr subPtr;
- subPtr.i = c_subPtr.curr.i;
- subPtr.p = suma.c_subscriptions.getPtr(subPtr.i);
-
- suma.c_subscriptions.next(c_subPtr);
-
- SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend();
-
- req->subscriberRef = suma.reference();
- req->subscriberData = subPtr.i;
- req->subscriptionId = subPtr.p->m_subscriptionId;
- req->subscriptionKey = subPtr.p->m_subscriptionKey;
- req->subscriptionType = subPtr.p->m_subscriptionType |
- SubCreateReq::RestartFlag;
-
- switch (subPtr.p->m_subscriptionType) {
- case SubCreateReq::TableEvent:
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot: {
- jam();
-
- Ptr<SyncRecord> syncPtr;
- suma.c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
- syncPtr.p->m_tableList.first(syncPtr.p->m_tableList_it);
-
- ndbrequire(!syncPtr.p->m_tableList_it.isNull());
-
- req->tableId = *syncPtr.p->m_tableList_it.data;
-
-#if 0
- for (int i = 0; i < MAX_TABLES; i++)
- if (subPtr.p->m_tables[i]) {
- req->tableId = i;
- break;
- }
-#endif
-
- suma.sendSignal(sumaRef, GSN_SUB_CREATE_REQ, signal,
- SubCreateReq::SignalLength+1 /*to get table Id*/, JBB);
- return;
- }
- case SubCreateReq::SingleTableScan :
- // TODO
- jam();
- return;
- }
- ndbrequire(false);
-}
-
-void
-Suma::execSUB_CREATE_CONF(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_CREATE_CONF");
-#endif
-
- const Uint32 senderRef = signal->senderBlockRef();
-
- SubCreateConf * const conf = (SubCreateConf *)signal->getDataPtr();
-
- Subscription key;
- const Uint32 subscriberData = conf->subscriberData;
- key.m_subscriptionId = conf->subscriptionId;
- key.m_subscriptionKey = conf->subscriptionKey;
-
- SubscriptionPtr subPtr;
- ndbrequire(c_subscriptions.find(subPtr, key));
-
- switch(subPtr.p->m_subscriptionType) {
- case SubCreateReq::TableEvent:
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot:
- {
- Ptr<SyncRecord> syncPtr;
- c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI);
-
- syncPtr.p->m_tableList.next(syncPtr.p->m_tableList_it);
- if (syncPtr.p->m_tableList_it.isNull()) {
- jam();
- SubSyncReq *req = (SubSyncReq *)signal->getDataPtrSend();
-
- req->subscriptionId = key.m_subscriptionId;
- req->subscriptionKey = key.m_subscriptionKey;
- req->subscriberData = subscriberData;
- req->part = (Uint32) SubscriptionData::MetaData;
-
- sendSignal(senderRef, GSN_SUB_SYNC_REQ, signal,
- SubSyncReq::SignalLength, JBB);
- } else {
- jam();
- SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend();
-
- req->subscriberRef = reference();
- req->subscriberData = subPtr.i;
- req->subscriptionId = subPtr.p->m_subscriptionId;
- req->subscriptionKey = subPtr.p->m_subscriptionKey;
- req->subscriptionType = subPtr.p->m_subscriptionType |
- SubCreateReq::RestartFlag |
- SubCreateReq::AddTableFlag;
-
- req->tableId = *syncPtr.p->m_tableList_it.data;
-
- sendSignal(senderRef, GSN_SUB_CREATE_REQ, signal,
- SubCreateReq::SignalLength+1 /*to get table Id*/, JBB);
- }
- }
- return;
- case SubCreateReq::SingleTableScan:
- ndbrequire(false);
- }
- ndbrequire(false);
-}
-
-void
-Suma::execSUB_CREATE_REF(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_CREATE_REF");
-#endif
- //ndbrequire(false);
-}
-
-void
-Suma::execSUB_SYNC_CONF(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_SYNC_CONF");
-#endif
- Uint32 sumaRef = signal->getSendersBlockRef();
-
- SubSyncConf *conf = (SubSyncConf *)signal->getDataPtr();
- Subscription key;
-
- key.m_subscriptionId = conf->subscriptionId;
- key.m_subscriptionKey = conf->subscriptionKey;
- // SubscriptionData::Part part = (SubscriptionData::Part)conf->part;
- // const Uint32 subscriberData = conf->subscriberData;
-
- SubscriptionPtr subPtr;
- c_subscriptions.find(subPtr, key);
-
- switch(subPtr.p->m_subscriptionType) {
- case SubCreateReq::TableEvent:
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot:
- jam();
- Restart.nextSubscription(signal, sumaRef);
- return;
- case SubCreateReq::SingleTableScan:
- ndbrequire(false);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Suma::execSUB_SYNC_REF(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_SYNC_REF");
-#endif
- //ndbrequire(false);
-}
-
-void
-Suma::execSUMA_START_ME(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUMA_START_ME");
-#endif
-
- Restart.runSUMA_START_ME(signal, signal->getSendersBlockRef());
-}
-
-void
-Suma::Restart::runSUMA_START_ME(Signal* signal, Uint32 sumaRef) {
- int I = suma.RtoI(sumaRef);
-
- // restarting Suma is ready for SUB_START_REQ
- if (c_waitingToStart[I]) {
- // we've waited with startSubscriber since restarting suma was not ready
- c_waitingToStart[I] = false;
- startSubscriber(signal, sumaRef);
- } else {
- // do startSubscriber as soon as its time
- c_okToStart[I] = true;
- }
-}
-
-void
-Suma::Restart::completeSubscription(Signal* signal, Uint32 sumaRef) {
- jam();
- int I = suma.RtoI(sumaRef);
-
- if (c_okToStart[I]) {// otherwise will start when START_ME comes
- c_okToStart[I] = false;
- startSubscriber(signal, sumaRef);
- } else {
- c_waitingToStart[I] = true;
- }
-}
-
-void
-Suma::Restart::startSubscriber(Signal* signal, Uint32 sumaRef) {
- jam();
- suma.c_dataSubscribers.first(c_subbPtr);
- nextSubscriber(signal, sumaRef);
-}
-
-void
-Suma::Restart::sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr,
- Signal* signal, Uint32 sumaRef)
-{
- jam();
- SubStartReq * req = (SubStartReq *)signal->getDataPtrSend();
-
- req->senderRef = suma.reference();
- req->senderData = subbPtr.p->m_senderData;
- req->subscriptionId = subPtr.p->m_subscriptionId;
- req->subscriptionKey = subPtr.p->m_subscriptionKey;
- req->part = SubscriptionData::TableData;
- req->subscriberData = subbPtr.p->m_subscriberData;
- req->subscriberRef = subbPtr.p->m_subscriberRef;
-
- // restarting suma will not respond to this until startphase 5
- // since it is not until then data copying has been completed
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::Restart::sendSubStartReq sending GSN_SUB_START_REQ id=%u key=%u",
- req->subscriptionId, req->subscriptionKey);
-#endif
- suma.sendSignal(sumaRef, GSN_SUB_START_REQ,
- signal, SubStartReq::SignalLength2, JBB);
-}
-
-void
-Suma::execSUB_START_CONF(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_START_CONF");
-#endif
- Uint32 sumaRef = signal->getSendersBlockRef();
- Restart.nextSubscriber(signal, sumaRef);
-}
-
-void
-Suma::execSUB_START_REF(Signal* signal) {
- jamEntry();
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUB_START_REF");
-#endif
- //ndbrequire(false);
-}
-
-void
-Suma::Restart::nextSubscriber(Signal* signal, Uint32 sumaRef) {
- jam();
- if (c_subbPtr.isNull()) {
- jam();
- completeSubscriber(signal, sumaRef);
- return;
- }
-
- SubscriberPtr subbPtr = c_subbPtr;
- suma.c_dataSubscribers.next(c_subbPtr);
-
- /*
- * get subscription ptr for this subscriber
- */
-
- SubscriptionPtr subPtr;
- suma.c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI);
- switch (subPtr.p->m_subscriptionType) {
- case SubCreateReq::TableEvent:
- case SubCreateReq::SelectiveTableSnapshot:
- case SubCreateReq::DatabaseSnapshot:
- {
- jam();
- sendSubStartReq(subPtr, subbPtr, signal, sumaRef);
-#if 0
- SubStartReq * req = (SubStartReq *)signal->getDataPtrSend();
-
- req->senderRef = reference();
- req->senderData = subbPtr.p->m_senderData;
- req->subscriptionId = subPtr.p->m_subscriptionId;
- req->subscriptionKey = subPtr.p->m_subscriptionKey;
- req->part = SubscriptionData::TableData;
- req->subscriberData = subbPtr.p->m_subscriberData;
- req->subscriberRef = subbPtr.p->m_subscriberRef;
-
- // restarting suma will not respond to this until startphase 5
- // since it is not until then data copying has been completed
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::nextSubscriber sending GSN_SUB_START_REQ id=%u key=%u",
- req->subscriptionId, req->subscriptionKey);
-#endif
- suma.sendSignal(sumaRef, GSN_SUB_START_REQ,
- signal, SubStartReq::SignalLength2, JBB);
-#endif
- }
- return;
- case SubCreateReq::SingleTableScan:
- ndbrequire(false);
- return;
- }
- ndbrequire(false);
-}
-
-void
-Suma::Restart::completeSubscriber(Signal* signal, Uint32 sumaRef) {
- completeRestartingNode(signal, sumaRef);
-}
-
-void
-Suma::Restart::completeRestartingNode(Signal* signal, Uint32 sumaRef) {
- jam();
- SumaHandoverReq * req = (SumaHandoverReq *)signal->getDataPtrSend();
-
- req->gci = suma.getFirstGCI(signal);
-
- suma.sendSignal(sumaRef, GSN_SUMA_HANDOVER_REQ, signal,
- SumaHandoverReq::SignalLength, JBB);
-}
-
-// only run on restarting suma
-
-void
-Suma::execSUMA_HANDOVER_REQ(Signal* signal)
-{
- jamEntry();
- // Uint32 sumaRef = signal->getSendersBlockRef();
- SumaHandoverReq const * req = (SumaHandoverReq *)signal->getDataPtr();
-
- Uint32 gci = req->gci;
- Uint32 new_gci = getFirstGCI(signal);
-
- if (new_gci > gci) {
- gci = new_gci;
- }
-
- { // all recreated subscribers at restarting SUMA start at same GCI
- SubscriberPtr subbPtr;
- for(c_dataSubscribers.first(subbPtr);
- !subbPtr.isNull();
- c_dataSubscribers.next(subbPtr)){
- subbPtr.p->m_firstGCI = gci;
- }
- }
-
-#ifdef NODEFAIL_DEBUG
- ndbout_c("Suma::execSUMA_HANDOVER_REQ, gci = %u", gci);
-#endif
-
- c_handoverToDo = false;
- c_restartLock = false;
- {
-#ifdef HANDOVER_DEBUG
- int c = 0;
-#endif
- for( int i = 0; i < NO_OF_BUCKETS; i++) {
- jam();
- if (getResponsibleSumaNodeId(i) == refToNode(reference())) {
-#ifdef HANDOVER_DEBUG
- c++;
-#endif
- jam();
- c_buckets[i].active = false;
- c_buckets[i].handoverGCI = gci;
- c_buckets[i].handover = true;
- c_buckets[i].handover_started = false;
- c_handoverToDo = true;
- }
- }
-#ifdef HANDOVER_DEBUG
- ndbout_c("prepared handover of bucket %u buckets", c);
-#endif
- }
-
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- jam();
- Uint32 ref = calcSumaBlockRef(c_nodesInGroup[i]);
- if (ref != reference()) {
- jam();
- sendSignal(ref, GSN_SUMA_HANDOVER_CONF, signal,
- SumaHandoverConf::SignalLength, JBB);
- }//if
- }
-}
-
-// only run on all but restarting suma
-void
-Suma::execSUMA_HANDOVER_CONF(Signal* signal) {
- jamEntry();
- Uint32 sumaRef = signal->getSendersBlockRef();
- SumaHandoverConf const * conf = (SumaHandoverConf *)signal->getDataPtr();
-
- Uint32 gci = conf->gci;
-
-#ifdef HANDOVER_DEBUG
- ndbout_c("Suma::execSUMA_HANDOVER_CONF, gci = %u", gci);
-#endif
-
- /* TODO, if we are restarting several SUMA's (>2 in a nodegroup)
- * we have to collect all these conf's before proceding
- */
-
- // restarting node is now prepared and ready
- c_preparingNodes.clear(refToNode(sumaRef)); /* !! important to do before
- * below since it affects
- * getResponsibleSumaNodeId()
- */
-
- c_handoverToDo = false;
- // mark all active buckets really belonging to restarting SUMA
- for( int i = 0; i < NO_OF_BUCKETS; i++) {
- if (c_buckets[i].active) {
- // I'm running this bucket
- if (getResponsibleSumaNodeId(i) == refToNode(sumaRef)) {
- // but it should really be the restarted node
- c_buckets[i].handoverGCI = gci;
- c_buckets[i].handover = true;
- c_buckets[i].handover_started = false;
- c_handoverToDo = true;
- }
- }
- }
-}
-
template void append(DataBuffer<11>&,SegmentedSectionPtr,SectionSegmentPool&);
diff --git a/ndb/src/kernel/blocks/suma/Suma.hpp b/ndb/src/kernel/blocks/suma/Suma.hpp
index 0bc56e51c4f..5cf1c4d543f 100644
--- a/ndb/src/kernel/blocks/suma/Suma.hpp
+++ b/ndb/src/kernel/blocks/suma/Suma.hpp
@@ -77,14 +77,6 @@ protected:
void execSUB_SYNC_CONTINUE_CONF(Signal* signal);
/**
- * Trigger logging
- */
- void execTRIG_ATTRINFO(Signal* signal);
- void execFIRE_TRIG_ORD(Signal* signal);
- void execSUB_GCP_COMPLETE_REP(Signal* signal);
- void runSUB_GCP_COMPLETE_ACC(Signal* signal);
-
- /**
* DIH signals
*/
void execDI_FCOUNTREF(Signal* signal);
@@ -93,14 +85,6 @@ protected:
void execDIGETPRIMCONF(Signal* signal);
/**
- * Trigger administration
- */
- void execCREATE_TRIG_REF(Signal* signal);
- void execCREATE_TRIG_CONF(Signal* signal);
- void execDROP_TRIG_REF(Signal* signal);
- void execDROP_TRIG_CONF(Signal* signal);
-
- /**
* continueb
*/
void execCONTINUEB(Signal* signal);
@@ -190,22 +174,6 @@ public:
void completeMeta(Signal*);
/**
- * Create triggers
- */
- Uint32 m_latestTriggerId;
- void startTrigger(Signal* signal);
- void nextTrigger(Signal* signal);
- void completeTrigger(Signal* signal);
- void createAttributeMask(AttributeMask&, Table*);
-
- /**
- * Drop triggers
- */
- void startDropTrigger(Signal* signal);
- void nextDropTrigger(Signal* signal);
- void completeDropTrigger(Signal* signal);
-
- /**
* Sync data
*/
Uint32 m_currentTable; // Index in m_tableList
@@ -229,18 +197,12 @@ public:
suma.progError(line, cause, extra);
}
- void runLIST_TABLES_CONF(Signal* signal);
void runGET_TABINFO_CONF(Signal* signal);
void runGET_TABINFOREF(Signal* signal);
void runDI_FCOUNTCONF(Signal* signal);
void runDIGETPRIMCONF(Signal* signal);
- void runCREATE_TRIG_CONF(Signal* signal);
- void runDROP_TRIG_CONF(Signal* signal);
- void runDROP_TRIG_REF(Signal* signal);
- void runDropTrig(Signal* signal, Uint32 triggerId, Uint32 tableId);
-
Uint32 ptrI;
union { Uint32 nextPool; Uint32 nextList; };
};
@@ -294,24 +256,11 @@ public:
Uint32 m_subscriberRef;
Uint32 m_subscriberData;
Uint32 m_subPtrI; //reference to subscription
- Uint32 m_firstGCI; // first GCI to send
- Uint32 m_lastGCI; // last acnowledged GCI
Uint32 nextList;
union { Uint32 nextPool; Uint32 prevList; };
};
typedef Ptr<Subscriber> SubscriberPtr;
- struct Bucket {
- bool active;
- bool handover;
- bool handover_started;
- Uint32 handoverGCI;
- };
-#define NO_OF_BUCKETS 24
- struct Bucket c_buckets[NO_OF_BUCKETS];
- bool c_handoverToDo;
- Uint32 c_lastCompleteGCI;
-
/**
*
*/
@@ -336,25 +285,8 @@ public:
DataBuffer<15>::DataBufferPool c_dataBufferPool;
/**
- * for restarting Suma not to start sending data too early
- */
- bool c_restartLock;
-
- /**
- * for flagging that a GCI containg inconsistent data
- * typically due to node failiure
- */
-
- Uint32 c_lastInconsistentGCI;
- Uint32 c_nodeFailGCI;
-
- NodeBitmask c_failedApiNodes;
-
- /**
* Functions
*/
- bool removeSubscribersOnNode(Signal *signal, Uint32 nodeId);
-
bool parseTable(Signal* signal, class GetTabInfoConf* conf, Uint32 tableId,
SyncRecord* syncPtr_p);
bool checkTableTriggers(SegmentedSectionPtr ptr);
@@ -365,52 +297,11 @@ public:
void sendSubIdRef(Signal* signal, Uint32 errorCode);
void sendSubCreateConf(Signal* signal, Uint32 sender, SubscriptionPtr subPtr);
void sendSubCreateRef(Signal* signal, const SubCreateReq& req, Uint32 errorCode);
- void sendSubStartRef(SubscriptionPtr subPtr, Signal* signal,
- Uint32 errorCode, bool temporary = false);
- void sendSubStartRef(Signal* signal,
- Uint32 errorCode, bool temporary = false);
- void sendSubStopRef(Signal* signal,
- Uint32 errorCode, bool temporary = false);
void sendSubSyncRef(Signal* signal, Uint32 errorCode);
void sendSubRemoveRef(Signal* signal, const SubRemoveReq& ref,
Uint32 errorCode, bool temporary = false);
- void sendSubStartComplete(Signal*, SubscriberPtr, Uint32,
- SubscriptionData::Part);
- void sendSubStopComplete(Signal*, SubscriberPtr);
- void sendSubStopReq(Signal* signal);
-
void completeSubRemoveReq(Signal* signal, SubscriptionPtr subPtr);
- Uint32 getFirstGCI(Signal* signal);
- Uint32 decideWhoToSend(Uint32 nBucket, Uint32 gci);
-
- virtual Uint32 getStoreBucket(Uint32 v) = 0;
- virtual Uint32 getResponsibleSumaNodeId(Uint32 D) = 0;
- virtual Uint32 RtoI(Uint32 sumaRef, bool dieOnNotFound = true) = 0;
-
- struct FailoverBuffer {
- // FailoverBuffer(DataBuffer<15>::DataBufferPool & p);
- FailoverBuffer();
-
- bool subTableData(Uint32 gci, Uint32 *src, int sz);
- bool subGcpCompleteRep(Uint32 gci);
- bool nodeFailRep();
-
- // typedef DataBuffer<15> GCIDataBuffer;
- // GCIDataBuffer m_GCIDataBuffer;
- // GCIDataBuffer::DataBufferIterator m_GCIDataBuffer_it;
-
- Uint32 *c_gcis;
- int c_sz;
-
- // Uint32 *c_buf;
- // int c_buf_sz;
-
- int c_first;
- int c_next;
- bool c_full;
- } c_failoverBuffer;
-
/**
* Table admin
*/
@@ -441,7 +332,7 @@ private:
* Framework signals
*/
- void getNodeGroupMembers(Signal* signal);
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void sendSTTORRY(Signal*);
@@ -452,35 +343,13 @@ private:
void execINCL_NODEREQ(Signal* signal);
void execCONTINUEB(Signal* signal);
void execSIGNAL_DROPPED_REP(Signal* signal);
- void execAPI_FAILREQ(Signal* signal) ;
-
- void execSUB_GCP_COMPLETE_ACC(Signal* signal);
/**
* Controller interface
*/
- void execSUB_CREATE_REF(Signal* signal);
- void execSUB_CREATE_CONF(Signal* signal);
-
- void execSUB_DROP_REF(Signal* signal);
- void execSUB_DROP_CONF(Signal* signal);
-
- void execSUB_START_REF(Signal* signal);
- void execSUB_START_CONF(Signal* signal);
-
- void execSUB_STOP_REF(Signal* signal);
- void execSUB_STOP_CONF(Signal* signal);
-
- void execSUB_SYNC_REF(Signal* signal);
- void execSUB_SYNC_CONF(Signal* signal);
-
void execSUB_ABORT_SYNC_REF(Signal* signal);
void execSUB_ABORT_SYNC_CONF(Signal* signal);
- void execSUMA_START_ME(Signal* signal);
- void execSUMA_HANDOVER_REQ(Signal* signal);
- void execSUMA_HANDOVER_CONF(Signal* signal);
-
/**
* Subscription generation interface
*/
@@ -492,49 +361,6 @@ private:
void execUTIL_SEQUENCE_REF(Signal* signal);
void execCREATE_SUBID_REQ(Signal* signal);
- Uint32 getStoreBucket(Uint32 v);
- Uint32 getResponsibleSumaNodeId(Uint32 D);
-
- /**
- * for Suma that is restarting another
- */
-
- struct Restart {
- Restart(Suma& s);
-
- Suma & suma;
-
- bool c_okToStart[MAX_REPLICAS];
- bool c_waitingToStart[MAX_REPLICAS];
-
- DLHashTable<SumaParticipant::Subscription>::Iterator c_subPtr; // TODO [MAX_REPLICAS]
- SubscriberPtr c_subbPtr; // TODO [MAX_REPLICAS]
-
- void progError(int line, int cause, const char * extra) {
- suma.progError(line, cause, extra);
- }
-
- void resetNode(Uint32 sumaRef);
- void runSUMA_START_ME(Signal*, Uint32 sumaRef);
- void startNode(Signal*, Uint32 sumaRef);
-
- void createSubscription(Signal* signal, Uint32 sumaRef);
- void nextSubscription(Signal* signal, Uint32 sumaRef);
- void completeSubscription(Signal* signal, Uint32 sumaRef);
-
- void startSync(Signal* signal, Uint32 sumaRef);
- void nextSync(Signal* signal, Uint32 sumaRef);
- void completeSync(Signal* signal, Uint32 sumaRef);
-
- void sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr,
- Signal* signal, Uint32 sumaRef);
- void startSubscriber(Signal* signal, Uint32 sumaRef);
- void nextSubscriber(Signal* signal, Uint32 sumaRef);
- void completeSubscriber(Signal* signal, Uint32 sumaRef);
-
- void completeRestartingNode(Signal* signal, Uint32 sumaRef);
- } Restart;
-
private:
friend class Restart;
struct SubCoordinator {
@@ -588,14 +414,4 @@ private:
DLList<SubCoordinator> c_runningSubscriptions;
};
-inline Uint32
-Suma::RtoI(Uint32 sumaRef, bool dieOnNotFound) {
- for (Uint32 i = 0; i < c_noNodesInGroup; i++) {
- if (sumaRef == calcSumaBlockRef(c_nodesInGroup[i]))
- return i;
- }
- ndbrequire(!dieOnNotFound);
- return RNIL;
-}
-
#endif
diff --git a/ndb/src/kernel/blocks/suma/SumaInit.cpp b/ndb/src/kernel/blocks/suma/SumaInit.cpp
index b5945db3811..ae7425da4bf 100644
--- a/ndb/src/kernel/blocks/suma/SumaInit.cpp
+++ b/ndb/src/kernel/blocks/suma/SumaInit.cpp
@@ -35,19 +35,11 @@ SumaParticipant::SumaParticipant(const Configuration & conf) :
*/
addRecSignal(GSN_SUB_CREATE_REQ, &SumaParticipant::execSUB_CREATE_REQ);
addRecSignal(GSN_SUB_REMOVE_REQ, &SumaParticipant::execSUB_REMOVE_REQ);
- addRecSignal(GSN_SUB_START_REQ, &SumaParticipant::execSUB_START_REQ);
- addRecSignal(GSN_SUB_STOP_REQ, &SumaParticipant::execSUB_STOP_REQ);
addRecSignal(GSN_SUB_SYNC_REQ, &SumaParticipant::execSUB_SYNC_REQ);
- addRecSignal(GSN_SUB_STOP_CONF, &SumaParticipant::execSUB_STOP_CONF);
- addRecSignal(GSN_SUB_STOP_REF, &SumaParticipant::execSUB_STOP_REF);
-
/**
* Dict interface
*/
- //addRecSignal(GSN_LIST_TABLES_REF, &SumaParticipant::execLIST_TABLES_REF);
- addRecSignal(GSN_LIST_TABLES_CONF, &SumaParticipant::execLIST_TABLES_CONF);
- //addRecSignal(GSN_GET_TABINFOREF, &SumaParticipant::execGET_TABINFO_REF);
addRecSignal(GSN_GET_TABINFO_CONF, &SumaParticipant::execGET_TABINFO_CONF);
addRecSignal(GSN_GET_TABINFOREF, &SumaParticipant::execGET_TABINFOREF);
#if 0
@@ -76,60 +68,6 @@ SumaParticipant::SumaParticipant(const Configuration & conf) :
addRecSignal(GSN_SUB_SYNC_CONTINUE_CONF,
&SumaParticipant::execSUB_SYNC_CONTINUE_CONF);
- /**
- * Trigger stuff
- */
- addRecSignal(GSN_TRIG_ATTRINFO, &SumaParticipant::execTRIG_ATTRINFO);
- addRecSignal(GSN_FIRE_TRIG_ORD, &SumaParticipant::execFIRE_TRIG_ORD);
-
- addRecSignal(GSN_CREATE_TRIG_REF, &Suma::execCREATE_TRIG_REF);
- addRecSignal(GSN_CREATE_TRIG_CONF, &Suma::execCREATE_TRIG_CONF);
- addRecSignal(GSN_DROP_TRIG_REF, &Suma::execDROP_TRIG_REF);
- addRecSignal(GSN_DROP_TRIG_CONF, &Suma::execDROP_TRIG_CONF);
-
- addRecSignal(GSN_SUB_GCP_COMPLETE_REP,
- &SumaParticipant::execSUB_GCP_COMPLETE_REP);
-
- /**
- * @todo: fix pool sizes
- */
- Uint32 noTables;
- const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
- ndbrequire(p != 0);
-
- ndb_mgm_get_int_parameter(p, CFG_DB_NO_TABLES,
- &noTables);
-
- c_tablePool_.setSize(noTables);
- c_tables.setSize(noTables);
-
- c_subscriptions.setSize(20); //10
- c_subscriberPool.setSize(64);
-
- c_subscriptionPool.setSize(64); //2
- c_syncPool.setSize(20); //2
- c_dataBufferPool.setSize(128);
-
- {
- SLList<SyncRecord> tmp(c_syncPool);
- Ptr<SyncRecord> ptr;
- while(tmp.seize(ptr))
- new (ptr.p) SyncRecord(* this, c_dataBufferPool);
- tmp.release();
- }
-
- for( int i = 0; i < NO_OF_BUCKETS; i++) {
- c_buckets[i].active = false;
- c_buckets[i].handover = false;
- c_buckets[i].handover_started = false;
- c_buckets[i].handoverGCI = 0;
- }
- c_handoverToDo = false;
- c_lastInconsistentGCI = RNIL;
- c_lastCompleteGCI = RNIL;
- c_nodeFailGCI = 0;
-
- c_failedApiNodes.clear();
}
SumaParticipant::~SumaParticipant()
@@ -138,49 +76,21 @@ SumaParticipant::~SumaParticipant()
Suma::Suma(const Configuration & conf) :
SumaParticipant(conf),
- Restart(*this),
c_nodes(c_nodePool),
c_runningSubscriptions(c_subCoordinatorPool)
{
-
- c_nodePool.setSize(MAX_NDB_NODES);
- c_masterNodeId = getOwnNodeId();
-
- c_nodeGroup = c_noNodesInGroup = c_idInNodeGroup = 0;
- for (int i = 0; i < MAX_REPLICAS; i++) {
- c_nodesInGroup[i] = 0;
- }
-
- c_subCoordinatorPool.setSize(10);
-
// Add received signals
+ addRecSignal(GSN_READ_CONFIG_REQ, &Suma::execREAD_CONFIG_REQ);
addRecSignal(GSN_STTOR, &Suma::execSTTOR);
addRecSignal(GSN_NDB_STTOR, &Suma::execNDB_STTOR);
addRecSignal(GSN_DUMP_STATE_ORD, &Suma::execDUMP_STATE_ORD);
addRecSignal(GSN_READ_NODESCONF, &Suma::execREAD_NODESCONF);
- addRecSignal(GSN_API_FAILREQ, &Suma::execAPI_FAILREQ);
- addRecSignal(GSN_NODE_FAILREP, &Suma::execNODE_FAILREP);
- addRecSignal(GSN_INCL_NODEREQ, &Suma::execINCL_NODEREQ);
addRecSignal(GSN_CONTINUEB, &Suma::execCONTINUEB);
addRecSignal(GSN_SIGNAL_DROPPED_REP, &Suma::execSIGNAL_DROPPED_REP, true);
addRecSignal(GSN_UTIL_SEQUENCE_CONF, &Suma::execUTIL_SEQUENCE_CONF);
addRecSignal(GSN_UTIL_SEQUENCE_REF, &Suma::execUTIL_SEQUENCE_REF);
addRecSignal(GSN_CREATE_SUBID_REQ,
&Suma::execCREATE_SUBID_REQ);
-
- addRecSignal(GSN_SUB_CREATE_CONF, &Suma::execSUB_CREATE_CONF);
- addRecSignal(GSN_SUB_CREATE_REF, &Suma::execSUB_CREATE_REF);
- addRecSignal(GSN_SUB_SYNC_CONF, &Suma::execSUB_SYNC_CONF);
- addRecSignal(GSN_SUB_SYNC_REF, &Suma::execSUB_SYNC_REF);
- addRecSignal(GSN_SUB_START_CONF, &Suma::execSUB_START_CONF);
- addRecSignal(GSN_SUB_START_REF, &Suma::execSUB_START_REF);
-
- addRecSignal(GSN_SUMA_START_ME, &Suma::execSUMA_START_ME);
- addRecSignal(GSN_SUMA_HANDOVER_REQ, &Suma::execSUMA_HANDOVER_REQ);
- addRecSignal(GSN_SUMA_HANDOVER_CONF, &Suma::execSUMA_HANDOVER_CONF);
-
- addRecSignal(GSN_SUB_GCP_COMPLETE_ACC,
- &Suma::execSUB_GCP_COMPLETE_ACC);
}
Suma::~Suma()
diff --git a/ndb/src/kernel/blocks/trix/Trix.cpp b/ndb/src/kernel/blocks/trix/Trix.cpp
index cd11cb4d575..1d6e5adad62 100644
--- a/ndb/src/kernel/blocks/trix/Trix.cpp
+++ b/ndb/src/kernel/blocks/trix/Trix.cpp
@@ -52,6 +52,7 @@ Trix::Trix(const Configuration & conf) :
BLOCK_CONSTRUCTOR(Trix);
// Add received signals
+ addRecSignal(GSN_READ_CONFIG_REQ, &Trix::execREAD_CONFIG_REQ);
addRecSignal(GSN_STTOR, &Trix::execSTTOR);
addRecSignal(GSN_NDB_STTOR, &Trix::execNDB_STTOR); // Forwarded from DICT
addRecSignal(GSN_READ_NODESCONF, &Trix::execREAD_NODESCONF);
@@ -85,6 +86,28 @@ Trix::Trix(const Configuration & conf) :
addRecSignal(GSN_SUB_SYNC_CONTINUE_REQ, &Trix::execSUB_SYNC_CONTINUE_REQ);
addRecSignal(GSN_SUB_META_DATA, &Trix::execSUB_META_DATA);
addRecSignal(GSN_SUB_TABLE_DATA, &Trix::execSUB_TABLE_DATA);
+}
+
+/**
+ *
+ */
+Trix::~Trix()
+{
+}
+
+void
+Trix::execREAD_CONFIG_REQ(Signal* signal)
+{
+ jamEntry();
+
+ const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
+
+ Uint32 ref = req->senderRef;
+ Uint32 senderData = req->senderData;
+
+ const ndb_mgm_configuration_iterator * p =
+ theConfiguration.getOwnConfigIterator();
+ ndbrequire(p != 0);
// Allocate pool sizes
c_theAttrOrderBufferPool.setSize(100);
@@ -96,13 +119,12 @@ Trix::Trix(const Configuration & conf) :
new (subptr.p) SubscriptionRecord(c_theAttrOrderBufferPool);
}
subscriptions.release();
-}
-/**
- *
- */
-Trix::~Trix()
-{
+ ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
+ conf->senderRef = reference();
+ conf->senderData = senderData;
+ sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
+ ReadConfigConf::SignalLength, JBB);
}
/**
diff --git a/ndb/src/kernel/blocks/trix/Trix.hpp b/ndb/src/kernel/blocks/trix/Trix.hpp
index 8dc01375fa1..78c5b8b35c3 100644
--- a/ndb/src/kernel/blocks/trix/Trix.hpp
+++ b/ndb/src/kernel/blocks/trix/Trix.hpp
@@ -139,6 +139,7 @@ private:
ArrayList<SubscriptionRecord> c_theSubscriptions;
// System start
+ void execREAD_CONFIG_REQ(Signal* signal);
void execSTTOR(Signal* signal);
void execNDB_STTOR(Signal* signal);
diff --git a/ndb/src/kernel/error/Error.hpp b/ndb/src/kernel/error/Error.hpp
deleted file mode 100644
index e19d6782793..00000000000
--- a/ndb/src/kernel/error/Error.hpp
+++ /dev/null
@@ -1,85 +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 ERROR_H
-#define ERROR_H
-
-/**
- * Errorcodes for NDB
- *
- * These errorcodes should be used whenever a condition
- * is detected where it's necesssary to shutdown NDB.
- *
- * Example: When another node fails while a NDB node are performing
- * a system restart the node should be shutdown. This
- * is kind of an error but the cause of the error is known
- * and a proper errormessage describing the problem should
- * be printed in error.log. It's therefore important to use
- * the proper errorcode.
- *
- * TODO: In the future the errorcodes should be classified
- *
- */
-
-enum ErrorCategory
-{
- warning,
- ecError,
- fatal,
- assert
-};
-
-const int ERR_BASE = 1000;
-
-// Errorcodes for all blocks except filseystem
-const int ERR_ERR_BASE = ERR_BASE + 1300;
-const int ERR_ERROR_PRGERR = ERR_ERR_BASE+1;
-const int ERR_NODE_NOT_IN_CONFIG = ERR_ERR_BASE+2;
-const int ERR_SYSTEM_ERROR = ERR_ERR_BASE+3;
-const int ERR_INDEX_NOTINRANGE = ERR_ERR_BASE+4;
-const int ERR_ARBIT_SHUTDOWN = ERR_ERR_BASE+5;
-const int ERR_POINTER_NOTINRANGE = ERR_ERR_BASE+6;
-const int ERR_PROGRAMERROR = ERR_ERR_BASE+7;
-const int ERR_SR_OTHERNODEFAILED = ERR_ERR_BASE+8;
-const int ERR_NODE_NOT_DEAD = ERR_ERR_BASE+9;
-const int ERR_SR_REDOLOG = ERR_ERR_BASE+10;
-const int ERR_SR_RESTARTCONFLICT = ERR_ERR_BASE+11;
-const int ERR_NO_MORE_UNDOLOG = ERR_ERR_BASE+12;
-const int ERR_SR_UNDOLOG = ERR_ERR_BASE+13;
-const int ERR_MEMALLOC = ERR_ERR_BASE+27;
-const int BLOCK_ERROR_JBUFCONGESTION = ERR_ERR_BASE+34;
-const int ERROR_TIME_QUEUE_SHORT = ERR_ERR_BASE+35;
-const int ERROR_TIME_QUEUE_LONG = ERR_ERR_BASE+36;
-const int ERROR_TIME_QUEUE_DELAY = ERR_ERR_BASE+37;
-const int ERROR_TIME_QUEUE_INDEX = ERR_ERR_BASE+38;
-const int BLOCK_ERROR_BNR_ZERO = ERR_ERR_BASE+39;
-const int ERROR_WRONG_PRIO_LEVEL = ERR_ERR_BASE+40;
-const int ERR_NDBREQUIRE = ERR_ERR_BASE+41;
-const int ERR_ERROR_INSERT = ERR_ERR_BASE+42;
-const int ERR_INVALID_CONFIG = ERR_ERR_BASE+50;
-const int ERR_OUT_OF_LONG_SIGNAL_MEMORY = ERR_ERR_BASE+51;
-
-// Errorcodes for NDB filesystem
-const int AFS_ERR_BASE = ERR_BASE + 1800;
-const int AFS_ERROR_NOPATH = AFS_ERR_BASE+1;
-const int AFS_ERROR_CHANNALFULL = AFS_ERR_BASE+2;
-const int AFS_ERROR_NOMORETHREADS = AFS_ERR_BASE+3;
-const int AFS_ERROR_PARAMETER = AFS_ERR_BASE+4;
-const int AFS_ERROR_INVALIDPATH = AFS_ERR_BASE+5;
-const int AFS_ERROR_MAXOPEN = AFS_ERR_BASE+6;
-const int AFS_ERROR_ALLREADY_OPEN = AFS_ERR_BASE+7;
-
-#endif // ERROR_H
diff --git a/ndb/src/kernel/error/ErrorHandlingMacros.hpp b/ndb/src/kernel/error/ErrorHandlingMacros.hpp
index d8bb7ff759b..8c3454b1ba1 100644
--- a/ndb/src/kernel/error/ErrorHandlingMacros.hpp
+++ b/ndb/src/kernel/error/ErrorHandlingMacros.hpp
@@ -17,22 +17,27 @@
#ifndef ERRORHANDLINGMACROS_H
#define ERRORHANDLINGMACROS_H
+#include <ndbd_exit_codes.h>
#include "ErrorReporter.hpp"
-#include "Error.hpp"
extern const char programName[];
-#define ERROR_SET_SIGNAL(messageCategory, messageID, problemData, objectRef) \
- ErrorReporter::handleError(messageCategory, messageID, problemData, objectRef, NST_ErrorHandlerSignal)
-#define ERROR_SET(messageCategory, messageID, problemData, objectRef) \
- ErrorReporter::handleError(messageCategory, messageID, problemData, objectRef)
+enum NotUsed
+{
+ warning,
+ ecError,
+ fatal,
+ assert
+};
+
+#define ERROR_SET_SIGNAL(not_used, messageID, problemData, objectRef) \
+ ErrorReporter::handleError(messageID, problemData, objectRef, NST_ErrorHandlerSignal)
+#define ERROR_SET(not_used, messageID, problemData, objectRef) \
+ ErrorReporter::handleError(messageID, problemData, objectRef)
// Description:
// Call ErrorHandler with the supplied arguments. The
// ErrorHandler decides how to report the error.
// Parameters:
- // messageCategory IN A hint to the error handler how the
- // error should be reported. Can be
- // error, fatal (or warning, use WARNING_SET instead).
// messageID IN Code identifying the error. If less
// than 1000 a unix error is assumed. If
// greater than 1000 the code is treated
diff --git a/ndb/src/kernel/error/ErrorMessages.cpp b/ndb/src/kernel/error/ErrorMessages.cpp
deleted file mode 100644
index 059aa4af61c..00000000000
--- a/ndb/src/kernel/error/ErrorMessages.cpp
+++ /dev/null
@@ -1,75 +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 "ErrorMessages.hpp"
-
-struct ErrStruct {
- int fauldId;
- const char* text;
-};
-
-const ErrStruct errArray[] = {
-
- {2301, "Assertion, probably a programming error"},
- {2302, "Own Node Id not a NDB node, configuration error"},
- {2303, "System error"},
- {2304, "Index too large"},
- {2305, "Arbitrator shutdown"},
- {2306, "Pointer too large"},
- {2307, "Internal program error"},
- {2308, "Node failed during system restart"},
- {2309, "Node state conflict"},
- {2310, "Error while reading the REDO log"},
- {2311, "Conflict when selecting restart type"},
- {2312, "No more free UNDO log"},
- {2313, "Error while reading the datapages and UNDO log"},
- {2327, "Memory allocation failure"},
- {2334, "Job buffer congestion"},
- {2335, "Error in short time queue"},
- {2336, "Error in long time queue"},
- {2337, "Error in time queue, too long delay"},
- {2338, "Time queue index out of range"},
- {2339, "Send signal error"},
- {2340, "Wrong prio level when sending signal"},
- {2341, "Internal program error (failed ndbrequire)"},
- {2342, "Error insert executed" },
- {2350, "Invalid Configuration fetched from Management Server" },
-
- // Ndbfs error messages
- {2801, "No file system path"},
- {2802, "Channel is full"},
- {2803, "No more threads"},
- {2804, "Bad parameter"},
- {2805, "Illegal file system path"},
- {2806, "Max number of open files exceeded"},
- {2807, "File has already been opened"},
-
- // Sentinel
- {0, "No message slogan found"}
-
-};
-
-const unsigned short NO_OF_ERROR_MESSAGES = sizeof(errArray)/sizeof(ErrStruct);
-
-const char* lookupErrorMessage(int faultId)
-{
- int i = 0;
- while (errArray[i].fauldId != faultId && errArray[i].fauldId != 0)
- i++;
- return errArray[i].text;
-}
-
-
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index 25409db48a8..6c8bb1fe615 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -17,9 +17,8 @@
#include <ndb_global.h>
-#include "Error.hpp"
+#include <ndbd_exit_codes.h>
#include "ErrorReporter.hpp"
-#include "ErrorMessages.hpp"
#include <FastScheduler.hpp>
#include <DebuggerNames.hpp>
@@ -29,17 +28,9 @@
#include <NdbAutoPtr.hpp>
-#define MESSAGE_LENGTH 400
+#define MESSAGE_LENGTH 500
-const char* errorType[] = {
- "warning",
- "error",
- "fatal",
- "assert"
-};
-
-
-static int WriteMessage(ErrorCategory thrdType, int thrdMessageID,
+static int WriteMessage(int thrdMessageID,
const char* thrdProblemData,
const char* thrdObjRef,
Uint32 thrdTheEmulatedJamIndex,
@@ -116,24 +107,35 @@ ErrorReporter::get_trace_no(){
void
-ErrorReporter::formatMessage(ErrorCategory type,
- int faultID,
+ErrorReporter::formatMessage(int faultID,
const char* problemData,
const char* objRef,
const char* theNameOfTheTraceFile,
char* messptr){
int processId;
-
+ ndbd_exit_classification cl;
+ ndbd_exit_status st;
+ const char *exit_msg = ndbd_exit_message(faultID, &cl);
+ const char *exit_cl_msg = ndbd_exit_classification_message(cl, &st);
+ const char *exit_st_msg = ndbd_exit_status_message(st);
+
processId = NdbHost_GetProcessId();
BaseString::snprintf(messptr, MESSAGE_LENGTH,
- "Date/Time: %s\nType of error: %s\n"
- "Message: %s\nFault ID: %d\nProblem data: %s"
- "\nObject of reference: %s\nProgramName: %s\n"
- "ProcessID: %d\nTraceFile: %s\n%s\n***EOM***\n",
+ "Time: %s\n"
+ "Status: %s\n"
+ "Message: %s (%s)\n"
+ "Error: %d\n"
+ "Error data: %s\n"
+ "Error object: %s\n"
+ "Program: %s\n"
+ "Pid: %d\n"
+ "Trace: %s\n"
+ "Version: %s\n"
+ "***EOM***\n",
formatTimeStampString() ,
- errorType[type],
- lookupErrorMessage(faultID),
+ exit_st_msg,
+ exit_msg, exit_cl_msg,
faultID,
(problemData == NULL) ? "" : problemData,
objRef,
@@ -160,8 +162,10 @@ ErrorReporter::setErrorHandlerShutdownType(NdbShutdownType nst)
s_errorHandlerShutdownType = nst;
}
+void childReportError(int error);
+
void
-ErrorReporter::handleAssert(const char* message, const char* file, int line)
+ErrorReporter::handleAssert(const char* message, const char* file, int line, int ec)
{
char refMessage[100];
@@ -175,38 +179,26 @@ ErrorReporter::handleAssert(const char* message, const char* file, int line)
BaseString::snprintf(refMessage, 100, "%s line: %d (block: %s)",
file, line, blockName);
#endif
- WriteMessage(assert, ERR_ERROR_PRGERR, message, refMessage,
+ WriteMessage(ec, message, refMessage,
theEmulatedJamIndex, theEmulatedJam);
- NdbShutdown(s_errorHandlerShutdownType);
-}
+ childReportError(ec);
-void
-ErrorReporter::handleThreadAssert(const char* message,
- const char* file,
- int line)
-{
- char refMessage[100];
- BaseString::snprintf(refMessage, 100, "file: %s lineNo: %d - %s",
- file, line, message);
-
NdbShutdown(s_errorHandlerShutdownType);
-}//ErrorReporter::handleThreadAssert()
-
+}
void
-ErrorReporter::handleError(ErrorCategory type, int messageID,
+ErrorReporter::handleError(int messageID,
const char* problemData,
const char* objRef,
NdbShutdownType nst)
{
- type = ecError;
- // The value for type is not always set correctly in the calling function.
- // So, to correct this, we set it set it to the value corresponding to
- // the function that is called.
- WriteMessage(type, messageID, problemData,
+ WriteMessage(messageID, problemData,
objRef, theEmulatedJamIndex, theEmulatedJam);
- if(messageID == ERR_ERROR_INSERT){
+
+ childReportError(messageID);
+
+ if(messageID == NDBD_EXIT_ERROR_INSERT){
NdbShutdown(NST_ErrorInsert);
} else {
if (nst == NST_ErrorHandler)
@@ -216,7 +208,7 @@ ErrorReporter::handleError(ErrorCategory type, int messageID,
}
int
-WriteMessage(ErrorCategory thrdType, int thrdMessageID,
+WriteMessage(int thrdMessageID,
const char* thrdProblemData, const char* thrdObjRef,
Uint32 thrdTheEmulatedJamIndex,
Uint8 thrdTheEmulatedJam[]){
@@ -257,7 +249,7 @@ WriteMessage(ErrorCategory thrdType, int thrdMessageID,
" \n\n\n");
// ...and write the error-message...
- ErrorReporter::formatMessage(thrdType, thrdMessageID,
+ ErrorReporter::formatMessage(thrdMessageID,
thrdProblemData, thrdObjRef,
theTraceFileName, theMessage);
fprintf(stream, "%s", theMessage);
@@ -284,7 +276,7 @@ WriteMessage(ErrorCategory thrdType, int thrdMessageID,
fseek(stream, offset, SEEK_SET);
// ...and write the error-message there...
- ErrorReporter::formatMessage(thrdType, thrdMessageID,
+ ErrorReporter::formatMessage(thrdMessageID,
thrdProblemData, thrdObjRef,
theTraceFileName, theMessage);
fprintf(stream, "%s", theMessage);
diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp
index c5533df46f4..0ec84190238 100644
--- a/ndb/src/kernel/error/ErrorReporter.hpp
+++ b/ndb/src/kernel/error/ErrorReporter.hpp
@@ -18,9 +18,9 @@
#define ERRORREPORTER_H
#include <ndb_global.h>
+#include <ndbd_exit_codes.h>
#include "TimeModule.hpp"
-#include "Error.hpp"
#include <Emulator.hpp>
class ErrorReporter
@@ -29,25 +29,18 @@ public:
static void setErrorHandlerShutdownType(NdbShutdownType nst = NST_ErrorHandler);
static void handleAssert(const char* message,
const char* file,
- int line);
+ int line, int ec = NDBD_EXIT_PRGERR);
- static void handleThreadAssert(const char* message,
- const char* file,
- int line);
-
- static void handleError(ErrorCategory type,
- int faultID,
+ static void handleError(int faultID,
const char* problemData,
const char* objRef,
enum NdbShutdownType = NST_ErrorHandler);
- static void handleWarning(ErrorCategory type,
- int faultID,
+ static void handleWarning(int faultID,
const char* problemData,
const char* objRef);
- static void formatMessage(ErrorCategory type,
- int faultID,
+ static void formatMessage(int faultID,
const char* problemData,
const char* objRef,
const char* theNameOfTheTraceFile,
diff --git a/ndb/src/kernel/error/Makefile.am b/ndb/src/kernel/error/Makefile.am
index 54f3de2d76d..c58cdf80940 100644
--- a/ndb/src/kernel/error/Makefile.am
+++ b/ndb/src/kernel/error/Makefile.am
@@ -2,7 +2,7 @@ noinst_LIBRARIES = liberror.a
liberror_a_SOURCES = TimeModule.cpp \
ErrorReporter.cpp \
- ErrorMessages.cpp
+ ndbd_exit_codes.c
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_kernel.mk.am
diff --git a/ndb/src/kernel/error/ndbd_exit_codes.c b/ndb/src/kernel/error/ndbd_exit_codes.c
new file mode 100644
index 00000000000..07b276346a0
--- /dev/null
+++ b/ndb/src/kernel/error/ndbd_exit_codes.c
@@ -0,0 +1,261 @@
+/* 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 <ndbd_exit_codes.h>
+
+typedef struct ErrStruct {
+ int faultId;
+ ndbd_exit_classification classification;
+ const char* text;
+} ErrStruct;
+
+/**
+ * Shorter names in table below
+ */
+
+#define XST_S ndbd_exit_st_success
+#define XST_U ndbd_exit_st_unknown
+#define XST_P ndbd_exit_st_permanent
+#define XST_R ndbd_exit_st_temporary
+#define XST_I ndbd_exit_st_filesystem_error
+
+#define XNE ndbd_exit_cl_none
+#define XUE ndbd_exit_cl_unknown
+#define XIE ndbd_exit_cl_internal_error
+#define XCE ndbd_exit_cl_configuration_error
+#define XAE ndbd_exit_cl_arbitration_error
+#define XRE ndbd_exit_cl_restart_error
+#define XCR ndbd_exit_cl_resource_configuration_error
+#define XFF ndbd_exit_cl_filesystem_full_error
+#define XFI ndbd_exit_cl_filesystem_inconsistency_error
+#define XFL ndbd_exit_cl_filesystem_limit
+
+static const ErrStruct errArray[] =
+{
+ {NDBD_EXIT_PRGERR, XIE, "Assertion"},
+ {NDBD_EXIT_NODE_NOT_IN_CONFIG, XCE,
+ "node id in the configuration has the wrong type, (i.e. not an NDB node)"},
+ {NDBD_EXIT_SYSTEM_ERROR, XIE,
+ "System error, node killed during node restart by other node"},
+ {NDBD_EXIT_INDEX_NOTINRANGE, XIE, "Array index out of range"},
+ {NDBD_EXIT_ARBIT_SHUTDOWN, XAE, "Node lost connection to other nodes and "
+ "can not form a unpartitioned cluster, please investigate if there are "
+ "error(s) on other node(s)"},
+ {NDBD_EXIT_PARTITIONED_SHUTDOWN, XAE, "Partitioned cluster detected. "
+ "Please check if cluster is already running"},
+ {NDBD_EXIT_POINTER_NOTINRANGE, XIE, "Pointer too large"},
+ {NDBD_EXIT_SR_OTHERNODEFAILED, XRE, "Another node failed during system "
+ "restart, please investigate error(s) on other node(s)"},
+ {NDBD_EXIT_NODE_NOT_DEAD, XRE, "Internal node state conflict, "
+ "most probably resolved by restarting node again"},
+ {NDBD_EXIT_SR_REDOLOG, XFI, "Error while reading the REDO log"},
+ /* Currently unused? */
+ {2311, XIE, "Conflict when selecting restart type"},
+ {NDBD_EXIT_NO_MORE_UNDOLOG, XCR,
+ "No more free UNDO log, increase UndoIndexBuffer"},
+ {NDBD_EXIT_SR_UNDOLOG, XFI,
+ "Error while reading the datapages and UNDO log"},
+ {NDBD_EXIT_MEMALLOC, XCE, "Memory allocation failure, "
+ "please decrease some configuration parameters"},
+ {NDBD_EXIT_BLOCK_JBUFCONGESTION, XIE, "Job buffer congestion"},
+ {NDBD_EXIT_TIME_QUEUE_SHORT, XIE, "Error in short time queue"},
+ {NDBD_EXIT_TIME_QUEUE_LONG, XIE, "Error in long time queue"},
+ {NDBD_EXIT_TIME_QUEUE_DELAY, XIE, "Error in time queue, too long delay"},
+ {NDBD_EXIT_TIME_QUEUE_INDEX, XIE, "Time queue index out of range"},
+ {NDBD_EXIT_BLOCK_BNR_ZERO, XIE, "Send signal error"},
+ {NDBD_EXIT_WRONG_PRIO_LEVEL, XIE, "Wrong priority level when sending signal"},
+ {NDBD_EXIT_NDBREQUIRE, XIE, "Internal program error (failed ndbrequire)"},
+ {NDBD_EXIT_NDBASSERT, XIE, "Internal program error (failed ndbassert)"},
+ {NDBD_EXIT_ERROR_INSERT, XNE, "Error insert executed" },
+ /* this error message is complemented by additional info when generated */
+ {NDBD_EXIT_INVALID_CONFIG, XCE,
+ "Invalid configuration received from Management Server"},
+ /* this error message is complemented by additional info when
+ generated, such as signal, and text
+ */
+ {NDBD_EXIT_OS_SIGNAL_RECEIVED, XIE, "Error OS signal received"},
+
+ {NDBD_EXIT_SR_RESTARTCONFLICT, XRE,
+ "Partial system restart causing conflicting file systems"},
+
+ /* VM */
+ {NDBD_EXIT_OUT_OF_LONG_SIGNAL_MEMORY, XCR,
+ "Signal lost, out of long signal memory, please increase LongMessageBuffer"},
+ {NDBD_EXIT_WATCHDOG_TERMINATE, XIE, "WatchDog terminate, internal error "
+ "or massive overload on the machine running this node"},
+ {NDBD_EXIT_SIGNAL_LOST_SEND_BUFFER_FULL, XCR,
+ "Signal lost, out of send buffer memory, please increase SendBufferMemory or lower the load"},
+ {NDBD_EXIT_SIGNAL_LOST, XIE, "Signal lost (unknown reason)"},
+ {NDBD_EXIT_ILLEGAL_SIGNAL, XIE,
+ "Illegal signal (version mismatch a possibility)"},
+ {NDBD_EXIT_CONNECTION_SETUP_FAILED, XCE, "Connection setup failed"},
+
+ /* Ndbcntr */
+ {NDBD_EXIT_RESTART_TIMEOUT, XCE,
+ "Total restart time too long, consider increasing StartFailureTimeout "
+ "or investigate error(s) on other node(s)"},
+ {NDBD_EXIT_RESTART_DURING_SHUTDOWN, XRE,
+ "Node started while node shutdown in progress. "
+ "Please wait until shutdown complete before starting node"},
+
+ /* DIH */
+ {NDBD_EXIT_MAX_CRASHED_REPLICAS, XFL,
+ "Too many crashed replicas (8 consecutive node restart failures)"},
+ {NDBD_EXIT_MASTER_FAILURE_DURING_NR, XRE,
+ "Unhandled master failure during node restart"},
+ {NDBD_EXIT_LOST_NODE_GROUP, XAE,
+ "All nodes in a node group are unavailable"},
+ {NDBD_EXIT_NO_RESTORABLE_REPLICA, XFI,
+ "Unable to find a restorable replica"},
+
+ /* ACC */
+ {NDBD_EXIT_SR_OUT_OF_INDEXMEMORY, XCR,
+ "Out of index memory during system restart, please increase IndexMemory"},
+
+ /* TUP */
+ {NDBD_EXIT_SR_OUT_OF_DATAMEMORY, XCR,
+ "Out of data memory during system restart, please increase DataMemory"},
+
+ /* Ndbfs error messages */
+ /* Most codes will have additional info, such as OS error code */
+ {NDBD_EXIT_AFS_NOPATH, XIE, "No file system path"},
+ {2802, XIE, "Channel is full"},
+ {2803, XIE, "No more threads"},
+ {NDBD_EXIT_AFS_PARAMETER, XIE, "Bad parameter"},
+ {NDBD_EXIT_AFS_INVALIDPATH, XCE, "Illegal file system path"},
+ {NDBD_EXIT_AFS_MAXOPEN, XCR,
+ "Max number of open files exceeded, please increase MaxNoOfOpenFiles"},
+ {NDBD_EXIT_AFS_ALREADY_OPEN, XIE, "File has already been opened"},
+
+ {NDBD_EXIT_AFS_ENVIRONMENT , XIE, "Environment error using file"},
+ {NDBD_EXIT_AFS_TEMP_NO_ACCESS , XIE, "Temporary on access to file"},
+ {NDBD_EXIT_AFS_DISK_FULL , XFF, "The file system is full"},
+ {NDBD_EXIT_AFS_PERMISSION_DENIED , XCE, "Received permission denied for file"},
+ {NDBD_EXIT_AFS_INVALID_PARAM , XCE, "Invalid parameter for file"},
+ {NDBD_EXIT_AFS_UNKNOWN , XIE, "Unknown file system error"},
+ {NDBD_EXIT_AFS_NO_MORE_RESOURCES , XIE,
+ "System reports no more file system resources"},
+ {NDBD_EXIT_AFS_NO_SUCH_FILE , XFI, "File not found"},
+ {NDBD_EXIT_AFS_READ_UNDERFLOW , XFI, "Read underflow"},
+
+ /* Sentinel */
+ {0, XUE,
+ "No message slogan found (please report a bug if you get this error code)"}
+};
+
+typedef struct StatusExitMessage {
+ ndbd_exit_status status;
+ const char * message;
+} StatusExitMessage;
+
+typedef struct StatusExitClassification {
+ ndbd_exit_status status;
+ ndbd_exit_classification classification;
+ const char * message;
+} StatusExitClassification;
+
+/**
+ * Mapping between classification and status
+ */
+static
+const
+StatusExitMessage StatusExitMessageMapping[] = {
+ { XST_S, "Success"},
+ { XST_U ,"Unknown"},
+ { XST_P, "Permanent error, external action needed"},
+ { XST_R, "Temporary error, restart node"},
+ { XST_I, "Ndbd file system error, restart node initial"}
+};
+
+static
+const
+int NbExitStatus = sizeof(StatusExitMessageMapping)/sizeof(StatusExitMessage);
+
+static
+const
+StatusExitClassification StatusExitClassificationMapping[] = {
+ { XST_S, XNE, "No error"},
+ { XST_U, XUE, "Unknown"},
+ { XST_R, XIE, "Internal error, programming error or missing error message, "
+ "please report a bug"},
+ { XST_P, XCE, "Configuration error"},
+ { XST_R, XAE, "Arbitration error"},
+ { XST_R, XRE, "Restart error"},
+ { XST_P, XCR, "Resource configuration error"},
+ { XST_P, XFF, "File system full"},
+ { XST_I, XFI, "Ndbd file system inconsistency error, please report a bug"},
+ { XST_I, XFL, "Ndbd file system limit exceeded"}
+};
+
+static const int NbExitClassification =
+sizeof(StatusExitClassificationMapping)/sizeof(StatusExitClassification);
+
+const char *ndbd_exit_message(int faultId, ndbd_exit_classification *cl)
+{
+ int i = 0;
+ while (errArray[i].faultId != faultId && errArray[i].faultId != 0)
+ i++;
+ *cl = errArray[i].classification;
+ return errArray[i].text;
+}
+
+static const char* empty_xstring = "";
+
+const
+char *ndbd_exit_classification_message(ndbd_exit_classification classification,
+ ndbd_exit_status *status)
+{
+ int i;
+ for (i= 0; i < NbExitClassification; i++)
+ {
+ if (StatusExitClassificationMapping[i].classification == classification)
+ {
+ *status = StatusExitClassificationMapping[i].status;
+ return StatusExitClassificationMapping[i].message;
+ }
+ }
+ *status = XST_U;
+ return empty_xstring;
+}
+
+const char *ndbd_exit_status_message(ndbd_exit_status status)
+{
+ int i;
+ for (i= 0; i < NbExitStatus; i++)
+ if (StatusExitMessageMapping[i].status == status)
+ return StatusExitMessageMapping[i].message;
+ return empty_xstring;
+}
+
+int ndbd_exit_string(int err_no, char *str, unsigned int size)
+{
+ unsigned int len;
+
+ ndbd_exit_classification cl;
+ ndbd_exit_status st;
+ const char *msg = ndbd_exit_message(err_no, &cl);
+ if (msg[0] != '\0')
+ {
+ const char *cl_msg = ndbd_exit_classification_message(cl, &st);
+ const char *st_msg = ndbd_exit_status_message(st);
+
+ len = my_snprintf(str, size-1, "%s: %s: %s", msg, st_msg, cl_msg);
+ str[size-1]= '\0';
+
+ return len;
+ }
+ return -1;
+}
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index d9953b920d2..649ae7cae3f 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -19,6 +19,7 @@
#include <ndb_version.h>
#include "Configuration.hpp"
+#include <ConfigRetriever.hpp>
#include <TransporterRegistry.hpp>
#include "vm/SimBlockList.hpp"
@@ -36,6 +37,10 @@
#include <NdbAutoPtr.hpp>
+#include <Properties.hpp>
+
+#include <mgmapi_debug.h>
+
#if defined NDB_SOLARIS // ok
#include <sys/processor.h> // For system informatio
#endif
@@ -58,16 +63,183 @@ extern "C" void handler_sigusr1(int signum); // child signalling failed restart
void systemInfo(const Configuration & conf,
const LogLevel & ll);
+// These are used already before fork if fetch_configuration() fails
+// (e.g. Unable to alloc node id). Set them to something reasonable.
+static FILE *child_info_file_r= stdin;
+static FILE *child_info_file_w= stdout;
+
+static void writeChildInfo(const char *token, int val)
+{
+ fprintf(child_info_file_w, "%s=%d\n", token, val);
+ fflush(child_info_file_w);
+}
+
+void childReportSignal(int signum)
+{
+ writeChildInfo("signal", signum);
+}
+
+void childReportError(int error)
+{
+ writeChildInfo("error", error);
+}
+
+void childExit(int code, Uint32 currentStartPhase)
+{
+ writeChildInfo("sphase", currentStartPhase);
+ writeChildInfo("exit", code);
+ fprintf(child_info_file_w, "\n");
+ fclose(child_info_file_r);
+ fclose(child_info_file_w);
+ exit(code);
+}
+
+void childAbort(int code, Uint32 currentStartPhase)
+{
+ writeChildInfo("sphase", currentStartPhase);
+ writeChildInfo("exit", code);
+ fprintf(child_info_file_w, "\n");
+ fclose(child_info_file_r);
+ fclose(child_info_file_w);
+ signal(6, SIG_DFL);
+ abort();
+}
+
+static int insert(const char * pair, Properties & p)
+{
+ BaseString tmp(pair);
+
+ tmp.trim(" \t\n\r");
+ Vector<BaseString> split;
+ tmp.split(split, ":=", 2);
+ if(split.size() != 2)
+ return -1;
+ p.put(split[0].trim().c_str(), split[1].trim().c_str());
+ return 0;
+}
+
+static int readChildInfo(Properties &info)
+{
+ fclose(child_info_file_w);
+ char buf[128];
+ while (fgets(buf,sizeof(buf),child_info_file_r))
+ insert(buf,info);
+ fclose(child_info_file_r);
+ return 0;
+}
+
+static bool get_int_property(Properties &info,
+ const char *token, Uint32 *int_val)
+{
+ const char *str_val= 0;
+ if (!info.get(token, &str_val))
+ return false;
+ char *endptr;
+ long int tmp= strtol(str_val, &endptr, 10);
+ if (str_val == endptr)
+ return false;
+ *int_val = tmp;
+ return true;
+}
+
+int reportShutdown(class Configuration *config, int error_exit, int restart)
+{
+ Uint32 error= 0, signum= 0, sphase= 256;
+ Properties info;
+ readChildInfo(info);
+
+ get_int_property(info, "signal", &signum);
+ get_int_property(info, "error", &error);
+ get_int_property(info, "sphase", &sphase);
+
+ Uint32 length, theData[25];
+ EventReport *rep = (EventReport *)theData;
+
+ rep->setNodeId(globalData.ownId);
+ if (restart)
+ theData[1] = 1 |
+ (globalData.theRestartFlag == initial_state ? 2 : 0) |
+ (config->getInitialStart() ? 4 : 0);
+ else
+ theData[1] = 0;
+
+ if (error_exit == 0)
+ {
+ rep->setEventType(NDB_LE_NDBStopCompleted);
+ theData[2] = signum;
+ length = 3;
+ }
+ else
+ {
+ rep->setEventType(NDB_LE_NDBStopForced);
+ theData[2] = signum;
+ theData[3] = error;
+ theData[4] = sphase;
+ theData[5] = 0; // extra
+ length = 6;
+ }
+
+ { // Log event
+ const EventReport * const eventReport = (EventReport *)&theData[0];
+ g_eventLogger.log(eventReport->getEventType(), theData,
+ eventReport->getNodeId(), 0);
+ }
+
+ for (unsigned n = 0; n < config->m_mgmds.size(); n++)
+ {
+ NdbMgmHandle h = ndb_mgm_create_handle();
+ if (h == 0 ||
+ ndb_mgm_set_connectstring(h, config->m_mgmds[n].c_str()) ||
+ ndb_mgm_connect(h,
+ 1, //no_retries
+ 0, //retry_delay_in_seconds
+ 0 //verbose
+ ))
+ goto handle_error;
+
+ {
+ if (ndb_mgm_report_event(h, theData, length))
+ goto handle_error;
+ }
+ goto do_next;
+
+handle_error:
+ if (h)
+ {
+ BaseString tmp(ndb_mgm_get_latest_error_msg(h));
+ tmp.append(" : ");
+ tmp.append(ndb_mgm_get_latest_error_desc(h));
+ g_eventLogger.warning("Unable to report shutdown reason to %s: %s",
+ config->m_mgmds[n].c_str(), tmp.c_str());
+ }
+ else
+ {
+ g_eventLogger.error("Unable to report shutdown reason to %s",
+ config->m_mgmds[n].c_str());
+ }
+do_next:
+ if (h)
+ {
+ ndb_mgm_disconnect(h);
+ ndb_mgm_destroy_handle(&h);
+ }
+ }
+ return 0;
+}
+
int main(int argc, char** argv)
{
NDB_INIT(argv[0]);
// Print to stdout/console
g_eventLogger.createConsoleHandler();
g_eventLogger.setCategory("ndbd");
+ g_eventLogger.enable(Logger::LL_ON, Logger::LL_INFO);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_CRITICAL);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_ERROR);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_WARNING);
+ g_eventLogger.m_logLevel.setLogLevel(LogLevel::llStartUp, 15);
+
globalEmulatorData.create();
// Parse command line options
@@ -96,22 +268,60 @@ int main(int argc, char** argv)
return 1;
}
}
-
+
#ifndef NDB_WIN32
signal(SIGUSR1, handler_sigusr1);
- for(pid_t child = fork(); child != 0; child = fork()){
+ pid_t child = -1;
+ while (! theConfig->getForegroundMode()) // the cond is const
+ {
+ // setup reporting between child and parent
+ int filedes[2];
+ if (pipe(filedes))
+ {
+ g_eventLogger.error("pipe() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ return 1;
+ }
+ else
+ {
+ if (!(child_info_file_w= fdopen(filedes[1],"w")))
+ {
+ g_eventLogger.error("fdopen() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ }
+ if (!(child_info_file_r= fdopen(filedes[0],"r")))
+ {
+ g_eventLogger.error("fdopen() failed with errno=%d (%s)",
+ errno, strerror(errno));
+ }
+ }
+
+ if ((child = fork()) <= 0)
+ break; // child or error
+
/**
* Parent
*/
+
catchsigs(true);
- int status = 0;
+ /**
+ * We no longer need the mgm connection in this process
+ * (as we are the angel, not ndb)
+ *
+ * We don't want to purge any allocated resources (nodeid), so
+ * we set that option to false
+ */
+ theConfig->closeConfiguration(false);
+
+ int status = 0, error_exit = 0, signum = 0;
while(waitpid(child, &status, 0) != child);
if(WIFEXITED(status)){
switch(WEXITSTATUS(status)){
case NRT_Default:
g_eventLogger.info("Angel shutting down");
+ reportShutdown(theConfig, 0, 0);
exit(0);
break;
case NRT_NoStart_Restart:
@@ -127,10 +337,12 @@ int main(int argc, char** argv)
globalData.theRestartFlag = perform_start;
break;
default:
+ error_exit = 1;
if(theConfig->stopOnError()){
/**
* Error shutdown && stopOnError()
*/
+ reportShutdown(theConfig, error_exit, 0);
exit(0);
}
// Fall-through
@@ -139,12 +351,27 @@ int main(int argc, char** argv)
globalData.theRestartFlag = perform_start;
break;
}
- } else if(theConfig->stopOnError()){
- /**
- * Error shutdown && stopOnError()
- */
- exit(0);
+ } else {
+ error_exit = 1;
+ if (WIFSIGNALED(status))
+ {
+ signum = WTERMSIG(status);
+ childReportSignal(signum);
+ }
+ else
+ {
+ signum = 127;
+ g_eventLogger.info("Unknown exit reason. Stopped.");
+ }
+ if(theConfig->stopOnError()){
+ /**
+ * Error shutdown && stopOnError()
+ */
+ reportShutdown(theConfig, error_exit, 0);
+ exit(0);
+ }
}
+
if (!failed_startup_flag)
{
// Reset the counter for consecutive failed startups
@@ -155,15 +382,23 @@ int main(int argc, char** argv)
/**
* Error shutdown && stopOnError()
*/
- g_eventLogger.alert("Ndbd has failed %u consecutive startups. Not restarting", failed_startups);
+ g_eventLogger.alert("Ndbd has failed %u consecutive startups. "
+ "Not restarting", failed_startups);
+ reportShutdown(theConfig, error_exit, 0);
exit(0);
}
failed_startup_flag = false;
+ reportShutdown(theConfig, error_exit, 1);
g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
theConfig->fetch_configuration();
}
- g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
+ if (child >= 0)
+ g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
+ else if (child > 0)
+ g_eventLogger.info("Ndb pid: %d", getpid());
+ else
+ g_eventLogger.info("Ndb started in foreground");
#else
g_eventLogger.info("Ndb started");
#endif
@@ -185,6 +420,10 @@ int main(int argc, char** argv)
FILE * signalLog = fopen(buf, "a");
globalSignalLoggers.setOwnNodeId(globalData.ownId);
globalSignalLoggers.setOutputStream(signalLog);
+#if 0 // to log startup
+ globalSignalLoggers.log(SignalLoggerManager::LogInOut, "BLOCK=DBDICT,DBDIH");
+ globalData.testOn = 1;
+#endif
#endif
catchsigs(false);
@@ -214,6 +453,13 @@ int main(int argc, char** argv)
exit(-1);
}
+ // Re-use the mgm handle as a transporter
+ if(!globalTransporterRegistry.connect_client(
+ theConfig->get_config_retriever()->get_mgmHandlePtr()))
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
+ "Connection to mgmd terminated before setup was complete",
+ "StopOnError missing");
+
if (!globalTransporterRegistry.start_clients()){
ndbout_c("globalTransporterRegistry.start_clients() failed");
exit(-1);
@@ -331,10 +577,7 @@ catchsigs(bool ignore){
#ifdef SIGPOLL
SIGPOLL,
#endif
- SIGSEGV,
-#ifdef SIGTRAP
- SIGTRAP
-#endif
+ SIGSEGV
};
static const int signals_ignore[] = {
@@ -348,6 +591,11 @@ catchsigs(bool ignore){
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);
+#ifdef SIGTRAP
+ Configuration* theConfig = globalEmulatorData.theConfiguration;
+ if (! theConfig->getForegroundMode())
+ handler_register(SIGTRAP, handler_error, ignore);
+#endif
#endif
}
@@ -355,6 +603,8 @@ extern "C"
void
handler_shutdown(int signum){
g_eventLogger.info("Received signal %d. Performing stop.", signum);
+ childReportError(0);
+ childReportSignal(signum);
globalData.theRestartFlag = perform_stop;
}
@@ -379,10 +629,15 @@ handler_error(int signum){
NdbSleep_MilliSleep(10);
thread_id= my_thread_id();
g_eventLogger.info("Received signal %d. Running error handler.", signum);
+ childReportSignal(signum);
// restart the system
- char errorData[40];
- BaseString::snprintf(errorData, 40, "Signal %d received", signum);
- ERROR_SET_SIGNAL(fatal, 0, errorData, __FILE__);
+ char errorData[64], *info= 0;
+#ifdef HAVE_STRSIGNAL
+ info= strsignal(signum);
+#endif
+ BaseString::snprintf(errorData, sizeof(errorData), "Signal %d received; %s", signum,
+ info ? info : "No text for signal available");
+ ERROR_SET_SIGNAL(fatal, NDBD_EXIT_OS_SIGNAL_RECEIVED, errorData, __FILE__);
}
extern "C"
diff --git a/ndb/src/kernel/vm/ArrayPool.hpp b/ndb/src/kernel/vm/ArrayPool.hpp
index 924ed51ee15..3b1264af8be 100644
--- a/ndb/src/kernel/vm/ArrayPool.hpp
+++ b/ndb/src/kernel/vm/ArrayPool.hpp
@@ -18,6 +18,7 @@
#define ARRAY_POOL_HPP
#include <ndb_global.h>
+#include "ndbd_malloc.hpp"
#include <pc.hpp>
#include <ErrorReporter.hpp>
@@ -44,7 +45,7 @@ public:
*
* Note, can currently only be called once
*/
- bool setSize(Uint32 noOfElements);
+ bool setSize(Uint32 noOfElements, bool exit_on_error = true);
inline Uint32 getNoOfFree() const {
return noOfFree;
@@ -201,7 +202,7 @@ template <class T>
inline
ArrayPool<T>::~ArrayPool(){
if(theArray != 0){
- NdbMem_Free(theArray);
+ ndbd_free(theArray, size * sizeof(T));
theArray = 0;
#ifdef ARRAY_GUARD
delete []theAllocatedBitmask;
@@ -218,13 +219,19 @@ ArrayPool<T>::~ArrayPool(){
template <class T>
inline
bool
-ArrayPool<T>::setSize(Uint32 noOfElements){
+ArrayPool<T>::setSize(Uint32 noOfElements, bool exit_on_error){
if(size == 0){
if(noOfElements == 0)
return true;
- theArray = (T *)NdbMem_Allocate(noOfElements * sizeof(T));
+ theArray = (T *)ndbd_malloc(noOfElements * sizeof(T));
if(theArray == 0)
- return false;
+ {
+ if (!exit_on_error)
+ return false;
+ ErrorReporter::handleAssert("ArrayPool<T>::setSize malloc failed",
+ __FILE__, __LINE__, NDBD_EXIT_MEMALLOC);
+ return false; // not reached
+ }
size = noOfElements;
noOfFree = noOfElements;
@@ -247,7 +254,11 @@ ArrayPool<T>::setSize(Uint32 noOfElements){
return true;
}
- return false;
+ if (!exit_on_error)
+ return false;
+
+ ErrorReporter::handleAssert("ArrayPool<T>::setSize called twice", __FILE__, __LINE__);
+ return false; // not reached
}
template <class T>
diff --git a/ndb/src/kernel/vm/CArray.hpp b/ndb/src/kernel/vm/CArray.hpp
index a6e84e2c041..93f75056b50 100644
--- a/ndb/src/kernel/vm/CArray.hpp
+++ b/ndb/src/kernel/vm/CArray.hpp
@@ -17,6 +17,8 @@
#ifndef CARRAY_HPP
#define CARRAY_HPP
+#include "ndbd_malloc.hpp"
+
/**
* Template class used for implementing an c - array
*/
@@ -31,7 +33,7 @@ public:
*
* Note, can currently only be called once
*/
- bool setSize(Uint32 noOfElements);
+ bool setSize(Uint32 noOfElements, bool exit_on_error = true);
/**
* Get size
@@ -69,7 +71,7 @@ template <class T>
inline
CArray<T>::~CArray(){
if(theArray != 0){
- NdbMem_Free(theArray);
+ ndbd_free(theArray, size * sizeof(T));
theArray = 0;
}
}
@@ -82,13 +84,19 @@ CArray<T>::~CArray(){
template <class T>
inline
bool
-CArray<T>::setSize(Uint32 noOfElements){
+CArray<T>::setSize(Uint32 noOfElements, bool exit_on_error){
if(size == noOfElements)
return true;
- theArray = (T *)NdbMem_Allocate(noOfElements * sizeof(T));
+ theArray = (T *)ndbd_malloc(noOfElements * sizeof(T));
if(theArray == 0)
- return false;
+ {
+ if (!exit_on_error)
+ return false;
+ ErrorReporter::handleAssert("CArray<T>::setSize malloc failed",
+ __FILE__, __LINE__, NDBD_EXIT_MEMALLOC);
+ return false; // not reached
+ }
size = noOfElements;
return true;
}
diff --git a/ndb/src/kernel/vm/ClusterConfiguration.cpp b/ndb/src/kernel/vm/ClusterConfiguration.cpp
index d5bd03f69d5..813407b497e 100644
--- a/ndb/src/kernel/vm/ClusterConfiguration.cpp
+++ b/ndb/src/kernel/vm/ClusterConfiguration.cpp
@@ -359,12 +359,12 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
if(!db.get(tmp[i].attrib, tmp[i].storage)){
char buf[255];
BaseString::snprintf(buf, sizeof(buf), "%s not found", tmp[i].attrib);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
}
if(!p.get("NoOfNodes", &cd.SizeAltData.noOfNodes)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "NoOfNodes missing");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "NoOfNodes missing");
}
Properties::Iterator it(&p);
@@ -378,36 +378,36 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
const Properties * node;
if(!p.get(name, &node)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data missing");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data missing");
}
if(!node->get("Id", &nodeId)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data (Id) missing");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Id) missing");
}
if(!node->get("Type", &nodeType)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data (Type) missing");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Type) missing");
}
if(nodeId > MAX_NODES){
char buf[255];
snprintf(buf, sizeof(buf),
"Maximum DB node id allowed is: %d", MAX_NDB_NODES);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
if(nodeId == 0){
char buf[255];
snprintf(buf, sizeof(buf),
"Minimum node id allowed in the cluster is: 1");
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
for(unsigned j = 0; j<nodeNo; j++){
if(cd.nodeData[j].nodeId == nodeId){
char buf[255];
BaseString::snprintf(buf, sizeof(buf), "Two node can not have the same node id");
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
}
@@ -430,14 +430,14 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
if(nodeId > MAX_NDB_NODES){
char buf[255];
BaseString::snprintf(buf, sizeof(buf), "Maximum node id for a ndb node is: %d", MAX_NDB_NODES);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
if(cd.SizeAltData.noOfNDBNodes > MAX_NDB_NODES){
char buf[255];
BaseString::snprintf(buf, sizeof(buf),
"Maximum %d ndb nodes is allowed in the cluster",
MAX_NDB_NODES);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
} else if(strcmp("API", nodeType) == 0){
cd.nodeData[nodeNo].nodeType = NodeInfo::API;
@@ -452,7 +452,7 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
cd.SizeAltData.noOfMGMNodes++; // No of MGM processes
tmpApiMgmProperties = "MGM";
} else {
- ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
"Invalid configuration: Unknown node type",
nodeType);
}
@@ -462,7 +462,7 @@ void ClusterConfiguration::init(const Properties & p, const Properties & db){
const Properties* q = 0;
if (!p.get(tmpApiMgmProperties, nodeId, &q)) {
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, tmpApiMgmProperties);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, tmpApiMgmProperties);
} else {
*/
Uint32 rank = 0;
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index de78a4e927c..7d1a5ed2ff4 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -48,11 +48,21 @@ extern EventLogger g_eventLogger;
enum ndbd_options {
OPT_INITIAL = NDB_STD_OPTIONS_LAST,
- OPT_NODAEMON
+ OPT_NODAEMON,
+ OPT_FOREGROUND,
+ OPT_NOWAIT_NODES,
+ OPT_INITIAL_START
};
NDB_STD_OPTS_VARS;
-static int _daemon, _no_daemon, _initial, _no_start;
+// XXX should be my_bool ???
+static int _daemon, _no_daemon, _foreground, _initial, _no_start;
+static int _initialstart;
+static const char* _nowait_nodes;
+
+extern Uint32 g_start_type;
+extern NdbNodeBitmask g_nowait_nodes;
+
/**
* Arguments to NDB process
*/
@@ -75,6 +85,19 @@ static struct my_option my_long_options[] =
"Do not start ndbd as daemon, provided for testing purposes",
(gptr*) &_no_daemon, (gptr*) &_no_daemon, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "foreground", OPT_FOREGROUND,
+ "Run real ndbd in foreground, provided for debugging purposes"
+ " (implies --nodaemon)",
+ (gptr*) &_foreground, (gptr*) &_foreground, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "nowait-nodes", OPT_NOWAIT_NODES,
+ "Nodes that will not be waited for during start",
+ (gptr*) &_nowait_nodes, (gptr*) &_nowait_nodes, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "initial-start", OPT_INITIAL_START,
+ "Perform initial start",
+ (gptr*) &_initialstart, (gptr*) &_initialstart, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static void short_usage_sub(void)
@@ -88,13 +111,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt,
- argument ? argument : "d:t:O,/tmp/ndbd.trace");
-}
bool
Configuration::init(int argc, char** argv)
@@ -103,16 +119,21 @@ Configuration::init(int argc, char** argv)
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndbd.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
exit(ho_error);
- if (_no_daemon) {
+ if (_no_daemon || _foreground) {
_daemon= 0;
}
DBUG_PRINT("info", ("no_start=%d", _no_start));
DBUG_PRINT("info", ("initial=%d", _initial));
DBUG_PRINT("info", ("daemon=%d", _daemon));
+ DBUG_PRINT("info", ("foreground=%d", _foreground));
DBUG_PRINT("info", ("connect_str=%s", opt_connect_str));
ndbSetOwnVersion();
@@ -134,6 +155,8 @@ Configuration::init(int argc, char** argv)
// Check daemon flag
if (_daemon)
_daemonMode = true;
+ if (_foreground)
+ _foregroundMode = true;
// Save programname
if(argc > 0 && argv[0] != 0)
@@ -143,6 +166,37 @@ Configuration::init(int argc, char** argv)
globalData.ownId= 0;
+ if (_nowait_nodes)
+ {
+ BaseString str(_nowait_nodes);
+ Vector<BaseString> arr;
+ str.split(arr, ",");
+ for (Uint32 i = 0; i<arr.size(); i++)
+ {
+ char *endptr = 0;
+ long val = strtol(arr[i].c_str(), &endptr, 10);
+ if (*endptr)
+ {
+ ndbout_c("Unable to parse nowait-nodes argument: %s : %s",
+ arr[i].c_str(), _nowait_nodes);
+ exit(-1);
+ }
+ if (! (val > 0 && val < MAX_NDB_NODES))
+ {
+ ndbout_c("Invalid nodeid specified in nowait-nodes: %d : %s",
+ val, _nowait_nodes);
+ exit(-1);
+ }
+ g_nowait_nodes.set(val);
+ }
+ }
+
+ if (_initialstart)
+ {
+ _initialStart = true;
+ g_start_type |= (1 << NodeState::ST_INITIAL_START);
+ }
+
return true;
}
@@ -154,11 +208,17 @@ Configuration::Configuration()
_backupPath = 0;
_initialStart = false;
_daemonMode = false;
+ _foregroundMode = false;
m_config_retriever= 0;
m_clusterConfig= 0;
+ m_clusterConfigIter= 0;
+ m_logLevel= 0;
}
Configuration::~Configuration(){
+ if (opt_connect_str)
+ free(_connectString);
+
if(_programName != NULL)
free(_programName);
@@ -171,10 +231,15 @@ Configuration::~Configuration(){
if (m_config_retriever) {
delete m_config_retriever;
}
+
+ if(m_logLevel) {
+ delete m_logLevel;
+ }
}
void
-Configuration::closeConfiguration(){
+Configuration::closeConfiguration(bool end_session){
+ m_config_retriever->end_session(end_session);
if (m_config_retriever) {
delete m_config_retriever;
}
@@ -191,13 +256,12 @@ Configuration::fetch_configuration(){
}
m_mgmd_port= 0;
- m_mgmd_host= 0;
m_config_retriever= new ConfigRetriever(getConnectString(),
NDB_VERSION, NODE_TYPE_DB);
if (m_config_retriever->hasError())
{
- ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
"Could not connect initialize handle to management server",
m_config_retriever->getErrorString());
}
@@ -209,11 +273,11 @@ Configuration::fetch_configuration(){
/* Set stop on error to true otherwise NDB will
go into an restart loop...
*/
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could not connect to ndb_mgmd", s);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Could not connect to ndb_mgmd", s);
}
m_mgmd_port= m_config_retriever->get_mgmd_port();
- m_mgmd_host= m_config_retriever->get_mgmd_host();
+ m_mgmd_host.assign(m_config_retriever->get_mgmd_host());
ConfigRetriever &cr= *m_config_retriever;
@@ -224,10 +288,11 @@ Configuration::fetch_configuration(){
if (globalData.ownId)
cr.setNodeId(globalData.ownId);
- globalData.ownId = cr.allocNodeId(2 /*retry*/,3 /*delay*/);
+ globalData.ownId = cr.allocNodeId(globalData.ownId ? 10 : 2 /*retry*/,
+ 3 /*delay*/);
if(globalData.ownId == 0){
- ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
"Unable to alloc node id", m_config_retriever->getErrorString());
}
@@ -241,7 +306,7 @@ Configuration::fetch_configuration(){
go into an restart loop...
*/
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Could not fetch configuration"
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Could not fetch configuration"
"/invalid configuration", s);
}
if(m_clusterConfig)
@@ -251,13 +316,36 @@ Configuration::fetch_configuration(){
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");
+ ERROR_SET(fatal, NDBD_EXIT_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",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"StopOnError missing");
}
+
+ m_mgmds.clear();
+ for(ndb_mgm_first(&iter); ndb_mgm_valid(&iter); ndb_mgm_next(&iter))
+ {
+ Uint32 nodeType, port;
+ char const *hostname;
+
+ ndb_mgm_get_int_parameter(&iter,CFG_TYPE_OF_SECTION,&nodeType);
+
+ if (nodeType != NodeInfo::MGM)
+ continue;
+
+ if (ndb_mgm_get_string_parameter(&iter,CFG_NODE_HOST, &hostname) ||
+ ndb_mgm_get_int_parameter(&iter,CFG_MGM_PORT, &port) ||
+ hostname == 0 || hostname[0] == 0)
+ {
+ continue;
+ }
+ BaseString connectstring(hostname);
+ connectstring.appfmt(":%d", port);
+
+ m_mgmds.push_back(connectstring);
+ }
}
static char * get_and_validate_path(ndb_mgm_configuration_iterator &iter,
@@ -265,12 +353,12 @@ static char * get_and_validate_path(ndb_mgm_configuration_iterator &iter,
{
const char* path = NULL;
if(iter.get(param, &path)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched missing ",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched missing ",
param_string);
}
if(path == 0 || strlen(path) == 0){
- ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG,
"Invalid configuration fetched. Configuration does not contain valid ",
param_string);
}
@@ -288,7 +376,7 @@ static char * get_and_validate_path(ndb_mgm_configuration_iterator &iter,
(::access(buf2, W_OK) != 0))
#endif
{
- ERROR_SET(fatal, AFS_ERROR_INVALIDPATH, path, " Filename::init()");
+ ERROR_SET(fatal, NDBD_EXIT_AFS_INVALIDPATH, path, param_string);
}
if (strcmp(&buf2[strlen(buf2) - 1], DIR_SEPARATOR))
@@ -312,7 +400,7 @@ Configuration::setupConfiguration(){
* p,
globalTransporterRegistry);
if(res <= 0){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"No transporters configured");
}
}
@@ -322,27 +410,27 @@ Configuration::setupConfiguration(){
*/
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");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched", "DB missing");
}
unsigned type;
if(!(iter.get(CFG_TYPE_OF_SECTION, &type) == 0 && type == NODE_TYPE_DB)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"I'm wrong type of node");
}
if(iter.get(CFG_DB_NO_SAVE_MSGS, &_maxErrorLogs)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"MaxNoOfSavedMessages missing");
}
if(iter.get(CFG_DB_MEMLOCK, &_lockPagesInMainMemory)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"LockPagesInMainMemory missing");
}
if(iter.get(CFG_DB_WATCHDOG_INTERVAL, &_timeBetweenWatchDogCheck)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"TimeBetweenWatchDogCheck missing");
}
@@ -357,7 +445,7 @@ Configuration::setupConfiguration(){
_backupPath= get_and_validate_path(iter, CFG_DB_BACKUP_DATADIR, "BackupDataDir");
if(iter.get(CFG_DB_STOP_ON_ERROR_INSERT, &m_restartOnErrorInsert)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, "Invalid configuration fetched",
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
"RestartOnErrorInsert missing");
}
@@ -372,6 +460,8 @@ Configuration::setupConfiguration(){
ConfigValues* cf = ConfigValuesFactory::extractCurrentSection(iter.m_config);
+ if(m_clusterConfigIter)
+ ndb_mgm_destroy_iterator(m_clusterConfigIter);
m_clusterConfigIter = ndb_mgm_create_configuration_iterator
(p, CFG_SECTION_NODE);
@@ -497,7 +587,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
*tmp[i].storage = 0;
} else {
BaseString::snprintf(buf, sizeof(buf),"ConfigParam: %d not found", tmp[i].paramId);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
}
}
@@ -507,12 +597,12 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
ndb_mgm_get_int64_parameter(&db, CFG_DB_INDEX_MEM, &indexMem);
if(dataMem == 0){
BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_DATA_MEM);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
if(indexMem == 0){
BaseString::snprintf(buf, sizeof(buf), "ConfigParam: %d not found", CFG_DB_INDEX_MEM);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
noOfDataPages = (dataMem / 32768);
@@ -536,23 +626,23 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
Uint32 nodeType;
if(ndb_mgm_get_int_parameter(p, CFG_NODE_ID, &nodeId)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data (Id) missing");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Id) missing");
}
if(ndb_mgm_get_int_parameter(p, CFG_TYPE_OF_SECTION, &nodeType)){
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, "Node data (Type) missing");
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, "Node data (Type) missing");
}
if(nodeId > MAX_NODES || nodeId == 0){
BaseString::snprintf(buf, sizeof(buf),
"Invalid node id: %d", nodeId);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
if(nodes.get(nodeId)){
BaseString::snprintf(buf, sizeof(buf), "Two node can not have the same node id: %d",
nodeId);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
nodes.set(nodeId);
@@ -563,7 +653,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
if(nodeId > MAX_NDB_NODES){
BaseString::snprintf(buf, sizeof(buf), "Maximum node id for a ndb node is: %d",
MAX_NDB_NODES);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
break;
case NODE_TYPE_API:
@@ -578,7 +668,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
break;
default:
BaseString::snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
- ERROR_SET(fatal, ERR_INVALID_CONFIG, msg, buf);
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
}
}
noOfNodes = nodeNo;
diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp
index acf0e163a84..6315209ddbb 100644
--- a/ndb/src/kernel/vm/Configuration.hpp
+++ b/ndb/src/kernel/vm/Configuration.hpp
@@ -17,6 +17,7 @@
#ifndef Configuration_H
#define Configuration_H
+#include <util/BaseString.hpp>
#include <mgmapi.h>
#include <ndb_types.h>
@@ -34,7 +35,7 @@ public:
void fetch_configuration();
void setupConfiguration();
- void closeConfiguration();
+ void closeConfiguration(bool end_session= true);
bool lockPagesInMainMemory() const;
@@ -63,16 +64,20 @@ public:
bool getInitialStart() const;
void setInitialStart(bool val);
bool getDaemonMode() const;
+ bool getForegroundMode() const;
const ndb_mgm_configuration_iterator * getOwnConfigIterator() const;
Uint32 get_mgmd_port() const {return m_mgmd_port;};
- const char *get_mgmd_host() const {return m_mgmd_host;};
+ const char *get_mgmd_host() const {return m_mgmd_host.c_str();};
+ ConfigRetriever* get_config_retriever() { return m_config_retriever; };
class LogLevel * m_logLevel;
private:
friend class Cmvmi;
friend class Qmgr;
+ friend int reportShutdown(class Configuration *config, int error, int restart);
+
ndb_mgm_configuration_iterator * getClusterConfigIterator() const;
Uint32 _stopOnError;
@@ -89,6 +94,8 @@ private:
ConfigRetriever *m_config_retriever;
+ Vector<BaseString> m_mgmds;
+
/**
* arguments to NDB process
*/
@@ -98,8 +105,9 @@ private:
bool _initialStart;
char * _connectString;
Uint32 m_mgmd_port;
- const char *m_mgmd_host;
- bool _daemonMode;
+ BaseString m_mgmd_host;
+ bool _daemonMode; // if not, angel in foreground
+ bool _foregroundMode; // no angel, raw ndbd in foreground
void calcSizeAlt(class ConfigValues * );
};
@@ -134,4 +142,10 @@ Configuration::getDaemonMode() const {
return _daemonMode;
}
+inline
+bool
+Configuration::getForegroundMode() const {
+ return _foregroundMode;
+}
+
#endif
diff --git a/ndb/src/kernel/vm/DLFifoList.hpp b/ndb/src/kernel/vm/DLFifoList.hpp
index b139ade831d..963ab007b65 100644
--- a/ndb/src/kernel/vm/DLFifoList.hpp
+++ b/ndb/src/kernel/vm/DLFifoList.hpp
@@ -115,6 +115,13 @@ public:
*/
bool hasNext(const Ptr<T> &) const;
+ /**
+ * Check if prev exists i.e. this is not first
+ *
+ * NOTE ptr must be both p & i
+ */
+ bool hasPrev(const Ptr<T> &) const;
+
Uint32 noOfElements() const {
Uint32 c = 0;
Uint32 i = head.firstItem;
@@ -357,4 +364,11 @@ DLFifoList<T>::hasNext(const Ptr<T> & p) const {
return p.p->nextList != RNIL;
}
+template <class T>
+inline
+bool
+DLFifoList<T>::hasPrev(const Ptr<T> & p) const {
+ return p.p->prevList != RNIL;
+}
+
#endif
diff --git a/ndb/src/kernel/vm/Emulator.cpp b/ndb/src/kernel/vm/Emulator.cpp
index 058829e05e2..e203ec4bde8 100644
--- a/ndb/src/kernel/vm/Emulator.cpp
+++ b/ndb/src/kernel/vm/Emulator.cpp
@@ -35,11 +35,16 @@
#include <EventLogger.hpp>
+void childExit(int code, Uint32 currentStartPhase);
+void childAbort(int code, Uint32 currentStartPhase);
+
extern "C" {
extern void (* ndb_new_handler)();
}
extern EventLogger g_eventLogger;
extern my_bool opt_core;
+// instantiated and updated in NdbcntrMain.cpp
+extern Uint32 g_currentStartPhase;
/**
* Declare the global variables
@@ -76,7 +81,7 @@ EmulatorData::EmulatorData(){
void
ndb_new_handler_impl(){
- ERROR_SET(fatal, ERR_MEMALLOC, "New handler", "");
+ ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, "New handler", "");
}
void
@@ -106,13 +111,14 @@ EmulatorData::destroy(){
delete theSimBlockList; theSimBlockList = 0;
if(m_socket_server)
delete m_socket_server; m_socket_server = 0;
+ NdbMutex_Destroy(theShutdownMutex);
NdbMem_Destroy();
}
void
NdbShutdown(NdbShutdownType type,
- NdbRestartType restartType){
-
+ NdbRestartType restartType)
+{
if(type == NST_ErrorInsert){
type = NST_Restart;
restartType = (NdbRestartType)
@@ -181,12 +187,11 @@ NdbShutdown(NdbShutdownType type,
g_eventLogger.info("Watchdog shutdown completed - %s", exitAbort);
if (opt_core)
{
- signal(6, SIG_DFL);
- abort();
+ childAbort(-1,g_currentStartPhase);
}
else
{
- exit(-1);
+ childExit(-1,g_currentStartPhase);
}
}
@@ -241,12 +246,11 @@ NdbShutdown(NdbShutdownType type,
g_eventLogger.info("Error handler shutdown completed - %s", exitAbort);
if (opt_core)
{
- signal(6, SIG_DFL);
- abort();
+ childAbort(-1,g_currentStartPhase);
}
else
{
- exit(-1);
+ childExit(-1,g_currentStartPhase);
}
}
@@ -254,7 +258,7 @@ NdbShutdown(NdbShutdownType type,
* This is a normal restart, depend on angel
*/
if(type == NST_Restart){
- exit(restartType);
+ childExit(restartType,g_currentStartPhase);
}
g_eventLogger.info("Shutdown completed - exiting");
@@ -269,10 +273,9 @@ NdbShutdown(NdbShutdownType type,
if (type== NST_Watchdog){
g_eventLogger.info("Watchdog is killing system the hard way");
#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
- signal(6, SIG_DFL);
- abort();
+ childAbort(-1,g_currentStartPhase);
#else
- exit(-1);
+ childExit(-1,g_currentStartPhase);
#endif
}
diff --git a/ndb/src/kernel/vm/FastScheduler.cpp b/ndb/src/kernel/vm/FastScheduler.cpp
index d0b7af27463..ad24a6795a4 100644
--- a/ndb/src/kernel/vm/FastScheduler.cpp
+++ b/ndb/src/kernel/vm/FastScheduler.cpp
@@ -19,7 +19,6 @@
#include "Emulator.hpp"
#include "VMSignal.hpp"
-#include <Error.hpp>
#include <SignalLoggerManager.hpp>
#include <BlockNumbers.h>
@@ -395,7 +394,8 @@ void print_restart(FILE * output, Signal* signal, Uint32 aLevel);
void FastScheduler::dumpSignalMemory(FILE * output)
{
- Signal signal;
+ SignalT<25> signalT;
+ Signal &signal= *(Signal*)&signalT;
Uint32 ReadPtr[5];
Uint32 tJob;
Uint32 tLastJob;
@@ -444,21 +444,21 @@ void FastScheduler::dumpSignalMemory(FILE * output)
void
FastScheduler::prio_level_error()
{
- ERROR_SET(ecError, ERROR_WRONG_PRIO_LEVEL,
+ ERROR_SET(ecError, NDBD_EXIT_WRONG_PRIO_LEVEL,
"Wrong Priority Level", "FastScheduler.C");
}
void
jbuf_error()
{
- ERROR_SET(ecError, BLOCK_ERROR_JBUFCONGESTION,
+ ERROR_SET(ecError, NDBD_EXIT_BLOCK_JBUFCONGESTION,
"Job Buffer Full", "APZJobBuffer.C");
}
void
bnr_error()
{
- ERROR_SET(ecError, BLOCK_ERROR_BNR_ZERO,
+ ERROR_SET(ecError, NDBD_EXIT_BLOCK_BNR_ZERO,
"Block Number Zero", "FastScheduler.C");
}
@@ -484,16 +484,16 @@ print_restart(FILE * output, Signal* signal, Uint32 aLevel)
*/
void
FastScheduler::reportDoJobStatistics(Uint32 tMeanLoopCount) {
- Signal signal;
- memset(&signal.header, 0, sizeof(signal.header));
+ SignalT<2> signalT;
+ Signal &signal= *(Signal*)&signalT;
- signal.theData[0] = EventReport::JobStatistic;
- signal.theData[1] = tMeanLoopCount;
-
- memset(&signal.header, 0, sizeof(SignalHeader));
+ memset(&signal.header, 0, sizeof(signal.header));
signal.header.theLength = 2;
signal.header.theSendersSignalId = 0;
- signal.header.theSendersBlockRef = numberToRef(0, 0);
+ signal.header.theSendersBlockRef = numberToRef(0, 0);
+
+ signal.theData[0] = NDB_LE_JobStatistic;
+ signal.theData[1] = tMeanLoopCount;
execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
}
diff --git a/ndb/src/ndbapi/NdbCursorOperation.cpp b/ndb/src/kernel/vm/KeyDescriptor.hpp
index a9f84c4c110..456d64ce1d8 100644
--- a/ndb/src/ndbapi/NdbCursorOperation.cpp
+++ b/ndb/src/kernel/vm/KeyDescriptor.hpp
@@ -14,38 +14,28 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbCursorOperation.cpp
- * Include:
- * Link:
- * Author: UABMASD Martin Sköld INN/V Alzato
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Cursor support
- * Documentation:
- * Adjust: 2002-04-01 UABMASD First version.
- ****************************************************************************/
-
-#include <NdbCursorOperation.hpp>
-#include <NdbResultSet.hpp>
-
-NdbCursorOperation::NdbCursorOperation(Ndb* aNdb) :
-{
-}
-
-NdbCursorOperation::~NdbCursorOperation()
-{
- if (m_resultSet)
- delete m_resultSet;
-}
+#ifndef KEY_DESCRIPTOR_HPP
+#define KEY_DESCRIPTOR_HPP
-void NdbCursorOperation::cursInit()
-{
- // Initialize result set
-}
+#include <ndb_types.h>
+#include <ndb_limits.h>
+#include "CArray.hpp"
-NdbResultSet* NdbCursorOperation::getResultSet()
+struct KeyDescriptor
{
-}
-
-
+ KeyDescriptor () { noOfKeyAttr = hasCharAttr = noOfDistrKeys = 0; }
+
+ Uint8 noOfKeyAttr;
+ Uint8 hasCharAttr;
+ Uint8 noOfDistrKeys;
+ Uint8 unused;
+ struct KeyAttr
+ {
+ Uint32 attributeDescriptor;
+ CHARSET_INFO* charsetInfo;
+ } keyAttr[MAX_ATTRIBUTES_IN_INDEX];
+};
+
+extern CArray<KeyDescriptor> g_key_descriptor_pool;
+
+#endif
diff --git a/ndb/src/kernel/vm/Makefile.am b/ndb/src/kernel/vm/Makefile.am
index 0dce9285ae3..8f9bf92cb01 100644
--- a/ndb/src/kernel/vm/Makefile.am
+++ b/ndb/src/kernel/vm/Makefile.am
@@ -18,7 +18,7 @@ libkernel_a_SOURCES = \
SimplePropertiesSection.cpp \
SectionReader.cpp \
MetaData.cpp \
- Mutex.cpp SafeCounter.cpp
+ Mutex.cpp SafeCounter.cpp ndbd_malloc.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi
diff --git a/ndb/src/kernel/vm/MetaData.hpp b/ndb/src/kernel/vm/MetaData.hpp
index 11e262664c1..1000114a421 100644
--- a/ndb/src/kernel/vm/MetaData.hpp
+++ b/ndb/src/kernel/vm/MetaData.hpp
@@ -86,15 +86,9 @@ public:
/* Primary table of index otherwise RNIL */
Uint32 primaryTableId;
- /* Type of storage (memory/disk, not used) */
- DictTabInfo::StorageType storageType;
-
/* Type of fragmentation (small/medium/large) */
DictTabInfo::FragmentType fragmentType;
- /* Key type of fragmentation (pk/dist key/dist group) */
- DictTabInfo::FragmentKeyType fragmentKeyType;
-
/* Global checkpoint identity when table created */
Uint32 gciTableCreated;
@@ -166,7 +160,6 @@ public:
Uint32 attributeDescriptor;
/* Extended attributes */
- Uint32 extType;
Uint32 extPrecision;
Uint32 extScale;
Uint32 extLength;
diff --git a/ndb/src/kernel/vm/SafeCounter.cpp b/ndb/src/kernel/vm/SafeCounter.cpp
index b09ad08b026..542e43f9172 100644
--- a/ndb/src/kernel/vm/SafeCounter.cpp
+++ b/ndb/src/kernel/vm/SafeCounter.cpp
@@ -25,8 +25,8 @@ SafeCounterManager::SafeCounterManager(class SimulatedBlock & block)
{}
bool
-SafeCounterManager::setSize(Uint32 maxNoOfActiveMutexes) {
- return m_counterPool.setSize(maxNoOfActiveMutexes);
+SafeCounterManager::setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error) {
+ return m_counterPool.setSize(maxNoOfActiveMutexes, exit_on_error);
}
Uint32
diff --git a/ndb/src/kernel/vm/SafeCounter.hpp b/ndb/src/kernel/vm/SafeCounter.hpp
index 869a7ef671f..917a67f2508 100644
--- a/ndb/src/kernel/vm/SafeCounter.hpp
+++ b/ndb/src/kernel/vm/SafeCounter.hpp
@@ -63,7 +63,7 @@ class SafeCounterManager {
public:
SafeCounterManager(class SimulatedBlock &);
- bool setSize(Uint32 maxNoOfActiveMutexes);
+ bool setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error = true);
Uint32 getSize() const ;
void execNODE_FAILREP(Signal*);
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index 9b52ac65331..b4787209d55 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -25,11 +25,12 @@
#include <TransporterRegistry.hpp>
#include <SignalLoggerManager.hpp>
#include <FastScheduler.hpp>
-#include <NdbMem.h>
+#include "ndbd_malloc.hpp"
#include <signaldata/EventReport.hpp>
#include <signaldata/ContinueFragmented.hpp>
#include <signaldata/NodeStateSignalData.hpp>
#include <signaldata/FsRef.hpp>
+#include <signaldata/SignalDroppedRep.hpp>
#include <DebuggerNames.hpp>
#include "LongSignal.hpp"
@@ -140,7 +141,6 @@ SimulatedBlock::installSimulatedBlockFunctions(){
a[GSN_UTIL_LOCK_CONF] = &SimulatedBlock::execUTIL_LOCK_CONF;
a[GSN_UTIL_UNLOCK_REF] = &SimulatedBlock::execUTIL_UNLOCK_REF;
a[GSN_UTIL_UNLOCK_CONF] = &SimulatedBlock::execUTIL_UNLOCK_CONF;
- a[GSN_READ_CONFIG_REQ] = &SimulatedBlock::execREAD_CONFIG_REQ;
a[GSN_FSOPENREF] = &SimulatedBlock::execFSOPENREF;
a[GSN_FSCLOSEREF] = &SimulatedBlock::execFSCLOSEREF;
a[GSN_FSWRITEREF] = &SimulatedBlock::execFSWRITEREF;
@@ -148,6 +148,7 @@ SimulatedBlock::installSimulatedBlockFunctions(){
a[GSN_FSREMOVEREF] = &SimulatedBlock::execFSREMOVEREF;
a[GSN_FSSYNCREF] = &SimulatedBlock::execFSSYNCREF;
a[GSN_FSAPPENDREF] = &SimulatedBlock::execFSAPPENDREF;
+ a[GSN_NODE_START_REP] = &SimulatedBlock::execNODE_START_REP;
}
void
@@ -156,8 +157,8 @@ SimulatedBlock::addRecSignalImpl(GlobalSignalNumber gsn,
if(gsn > MAX_GSN || (!force && theExecArray[gsn] != 0)){
char errorMsg[255];
BaseString::snprintf(errorMsg, 255,
- "Illeagal signal (%d %d)", gsn, MAX_GSN);
- ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
+ "GSN %d(%d))", gsn, MAX_GSN);
+ ERROR_SET(fatal, NDBD_EXIT_ILLEGAL_SIGNAL, errorMsg, errorMsg);
}
theExecArray[gsn] = f;
}
@@ -173,8 +174,7 @@ SimulatedBlock::signal_error(Uint32 gsn, Uint32 len, Uint32 recBlockNo,
"Signal (GSN: %d, Length: %d, Rec Block No: %d)",
gsn, len, recBlockNo);
- ErrorReporter::handleError(ecError,
- BLOCK_ERROR_BNR_ZERO,
+ ErrorReporter::handleError(NDBD_EXIT_BLOCK_BNR_ZERO,
probData,
objRef);
}
@@ -668,7 +668,7 @@ SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear)
n,
size);
#endif
- p = NdbMem_Allocate(size);
+ p = ndbd_malloc(size);
if (p == NULL){
char buf1[255];
char buf2[255];
@@ -676,7 +676,7 @@ SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear)
getBlockName(number()), type);
BaseString::snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes",
(Uint32)s, (Uint32)n, (Uint32)size);
- ERROR_SET(fatal, ERR_MEMALLOC, buf1, buf2);
+ ERROR_SET(fatal, NDBD_EXIT_MEMALLOC, buf1, buf2);
}
if(clear){
@@ -699,11 +699,9 @@ void
SimulatedBlock::deallocRecord(void ** ptr,
const char * type, size_t s, size_t n){
(void)type;
- (void)s;
- (void)n;
if(* ptr != 0){
- NdbMem_Free(* ptr);
+ ndbd_free(* ptr, n*s);
* ptr = 0;
}
}
@@ -733,7 +731,7 @@ SimulatedBlock::progError(int line, int err_code, const char* extra) const {
BaseString::snprintf(&buf[0], 100, "%s (Line: %d) 0x%.8x",
aBlockName, line, magicStatus);
- ErrorReporter::handleError(ecError, err_code, extra, buf);
+ ErrorReporter::handleError(err_code, extra, buf);
}
@@ -743,7 +741,7 @@ SimulatedBlock::infoEvent(const char * msg, ...) const {
return;
Uint32 theData[25];
- theData[0] = EventReport::InfoEvent;
+ theData[0] = NDB_LE_InfoEvent;
char * buf = (char *)&(theData[1]);
va_list ap;
@@ -784,7 +782,7 @@ SimulatedBlock::warningEvent(const char * msg, ...) const {
return;
Uint32 theData[25];
- theData[0] = EventReport::WarningEvent;
+ theData[0] = NDB_LE_WarningEvent;
char * buf = (char *)&(theData[1]);
va_list ap;
@@ -854,9 +852,12 @@ SimulatedBlock::execNDB_TAMPER(Signal * signal){
void
SimulatedBlock::execSIGNAL_DROPPED_REP(Signal * signal){
- ErrorReporter::handleError(ecError,
- ERR_OUT_OF_LONG_SIGNAL_MEMORY,
- "Signal lost, out of long signal memory",
+ char msg[64];
+ const SignalDroppedRep * const rep = (SignalDroppedRep *)&signal->theData[0];
+ snprintf(msg, sizeof(msg), "%s GSN: %u (%u,%u)", getBlockName(number()),
+ rep->originalGsn, rep->originalLength,rep->originalSectionCount);
+ ErrorReporter::handleError(NDBD_EXIT_OUT_OF_LONG_SIGNAL_MEMORY,
+ msg,
__FILE__,
NST_ErrorHandler);
}
@@ -913,6 +914,20 @@ SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){
sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
}
+void
+SimulatedBlock::execNODE_START_REP(Signal* signal)
+{
+ // common stuff for all blocks
+
+ // block specific stuff by virtual method override (default empty)
+ exec_node_start_rep(signal);
+}
+
+void
+SimulatedBlock::exec_node_start_rep(Signal* signal)
+{
+}
+
#ifdef VM_TRACE_TIME
void
SimulatedBlock::clearTimes() {
@@ -1739,20 +1754,6 @@ void SimulatedBlock::execUTIL_UNLOCK_CONF(Signal* signal){
c_mutexMgr.execUTIL_UNLOCK_CONF(signal);
}
-void
-SimulatedBlock::execREAD_CONFIG_REQ(Signal* signal){
- const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
-
- Uint32 ref = req->senderRef;
- Uint32 senderData = req->senderData;
-
- ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
- conf->senderRef = reference();
- conf->senderData = senderData;
- sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
- ReadConfigConf::SignalLength, JBB);
-}
-
void
SimulatedBlock::ignoreMutexUnlockCallback(Signal* signal,
Uint32 ptrI, Uint32 retVal){
@@ -1865,3 +1866,128 @@ SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){
}
#endif
+
+#include "KeyDescriptor.hpp"
+
+Uint32
+SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
+ Uint32 *dst, Uint32 dstSize,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor * desc = g_key_descriptor_pool.getPtr(tab);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+
+ Uint32 i = 0;
+ Uint32 srcPos = 0;
+ Uint32 dstPos = 0;
+ while (i < noOfKeyAttr)
+ {
+ const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
+ Uint32 dstWords =
+ xfrm_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo,
+ src, srcPos, dst, dstPos, dstSize);
+ keyPartLen[i++] = dstWords;
+ if (unlikely(dstWords == 0))
+ return 0;
+ }
+
+ return dstPos;
+}
+
+Uint32
+SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ const Uint32* src, Uint32 & srcPos,
+ Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const
+{
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDesc);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ Uint32 dstWords = ~0;
+ uchar* dstPtr = (uchar*)&dst[dstPos];
+ const uchar* srcPtr = (const uchar*)&src[srcPos];
+
+ if (cs == NULL)
+ {
+ jam();
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ }
+ else
+ {
+ jam();
+ Uint32 typeId = AttributeDescriptor::getType(attrDesc);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ if (unlikely(!ok))
+ return 0;
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ /*
+ * Varchar end-spaces are ignored in comparisons. To get same hash
+ * we blank-pad to maximum length via strnxfrm.
+ */
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ if (unlikely(n == -1))
+ return 0;
+ while ((n & 3) != 0)
+ {
+ dstPtr[n++] = 0;
+ }
+ dstWords = (n >> 2);
+ }
+ dstPos += dstWords;
+ srcPos += srcWords;
+ return dstWords;
+}
+
+Uint32
+SimulatedBlock::create_distr_key(Uint32 tableId,
+ Uint32 *data,
+ const Uint32
+ keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tableId);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+ Uint32 noOfDistrKeys = desc->noOfDistrKeys;
+
+ Uint32 *src = data;
+ Uint32 *dst = data;
+ Uint32 i = 0;
+ Uint32 dstPos = 0;
+
+ if(keyPartLen)
+ {
+ while (i < noOfKeyAttr && noOfDistrKeys)
+ {
+ Uint32 attr = desc->keyAttr[i].attributeDescriptor;
+ Uint32 len = keyPartLen[i];
+ if(AttributeDescriptor::getDKey(attr))
+ {
+ noOfDistrKeys--;
+ memmove(dst+dstPos, src, len << 2);
+ dstPos += len;
+ }
+ src += len;
+ i++;
+ }
+ }
+ else
+ {
+ while (i < noOfKeyAttr && noOfDistrKeys)
+ {
+ Uint32 attr = desc->keyAttr[i].attributeDescriptor;
+ Uint32 len = AttributeDescriptor::getSizeInWords(attr);
+ if(AttributeDescriptor::getDKey(attr))
+ {
+ noOfDistrKeys--;
+ memmove(dst+dstPos, src, len << 2);
+ dstPos += len;
+ }
+ src += len;
+ i++;
+ }
+ }
+ return dstPos;
+}
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index 81b4fe7413e..4a3620a00ab 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -20,11 +20,13 @@
#include <NdbTick.h>
#include <kernel_types.h>
#include <ndb_version.h>
+#include <ndb_limits.h>
#include "VMSignal.hpp"
#include <RefConvert.hpp>
#include <BlockNumbers.h>
#include <GlobalSignalNumbers.h>
+
#include "pc.hpp"
#include <NodeInfo.hpp>
#include <NodeState.hpp>
@@ -32,7 +34,6 @@
#include "LongSignal.hpp"
#include <SignalLoggerManager.hpp>
-#include <Error.hpp>
#include <ErrorReporter.hpp>
#include <ErrorHandlingMacros.hpp>
@@ -385,6 +386,28 @@ protected:
*/
const NodeInfo & getNodeInfo(NodeId nodeId) const;
NodeInfo & setNodeInfo(NodeId);
+
+ /**********************
+ * Xfrm stuff
+ */
+
+ /**
+ * @return length
+ */
+ Uint32 xfrm_key(Uint32 tab, const Uint32* src,
+ Uint32 *dst, Uint32 dstSize,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
+
+ Uint32 xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ const Uint32* src, Uint32 & srcPos,
+ Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const;
+
+ /**
+ *
+ */
+ Uint32 create_distr_key(Uint32 tableId,
+ Uint32 *data,
+ const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const;
private:
NewVARIABLE* NewVarRef; /* New Base Address Table for block */
@@ -400,6 +423,8 @@ private:
void execSIGNAL_DROPPED_REP(Signal* signal);
void execCONTINUE_FRAGMENTED(Signal* signal);
+ void execNODE_START_REP(Signal* signal);
+ virtual void exec_node_start_rep(Signal* signal);
Uint32 c_fragmentIdCounter;
ArrayPool<FragmentInfo> c_fragmentInfoPool;
@@ -483,7 +508,6 @@ private:
void execUTIL_UNLOCK_REF(Signal* signal);
void execUTIL_UNLOCK_CONF(Signal* signal);
- void execREAD_CONFIG_REQ(Signal* signal);
protected:
void execUPGRADE(Signal* signal);
@@ -544,11 +568,11 @@ SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){
char errorMsg[255];
if (!(gsn <= MAX_GSN)) {
BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d too high)", gsn);
- ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
+ ERROR_SET(fatal, NDBD_EXIT_PRGERR, errorMsg, errorMsg);
}
if (!(theExecArray[gsn] != 0)) {
BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d not added)", gsn);
- ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
+ ERROR_SET(fatal, NDBD_EXIT_PRGERR, errorMsg, errorMsg);
}
ndbrequire(false);
}
diff --git a/ndb/src/kernel/vm/SuperPool.cpp b/ndb/src/kernel/vm/SuperPool.cpp
new file mode 100644
index 00000000000..65e5dd99629
--- /dev/null
+++ b/ndb/src/kernel/vm/SuperPool.cpp
@@ -0,0 +1,442 @@
+/* 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 "SuperPool.hpp"
+
+// SuperPool
+
+SuperPool::SuperPool(Uint32 pageSize, Uint32 pageBits) :
+ m_pageSize(SP_ALIGN_SIZE(pageSize, SP_ALIGN)),
+ m_pageBits(pageBits),
+ m_memRoot(0),
+ m_pageEnt(0),
+ m_typeCheck(0),
+ m_typeSeq(0),
+ m_pageList(),
+ m_totalSize(0),
+ m_initSize(0),
+ m_incrSize(0),
+ m_maxSize(0)
+{
+ assert(5 <= pageBits <= 30);
+}
+
+bool
+SuperPool::init()
+{
+ return true;
+}
+
+SuperPool::~SuperPool()
+{
+}
+
+SuperPool::PageEnt::PageEnt() :
+ m_pageType(0),
+ m_freeRecI(RNIL),
+ m_useCount(0),
+ m_nextPageI(RNIL),
+ m_prevPageI(RNIL)
+{
+}
+
+SuperPool::PageList::PageList() :
+ m_headPageI(RNIL),
+ m_tailPageI(RNIL),
+ m_pageCount(0)
+{
+}
+
+SuperPool::PageList::PageList(PtrI pageI) :
+ m_headPageI(pageI),
+ m_tailPageI(pageI),
+ m_pageCount(1)
+{
+}
+
+SuperPool::RecInfo::RecInfo(Uint32 recType, Uint32 recSize) :
+ m_recType(recType),
+ m_recSize(recSize),
+ m_maxUseCount(0),
+ m_currPageI(RNIL),
+ m_currFreeRecI(RNIL),
+ m_currUseCount(0),
+ m_totalUseCount(0),
+ m_totalRecCount(0),
+ m_freeList(),
+ m_activeList(),
+ m_fullList()
+{
+}
+
+SuperPool::PtrI
+SuperPool::getPageI(void* pageP)
+{
+ const Uint32 pageSize = m_pageSize;
+ const Uint32 pageBits = m_pageBits;
+ const Uint32 recBits = 32 - pageBits;
+ void* const memRoot = m_memRoot;
+ assert(pageP == SP_ALIGN_PTR(pageP, memRoot, pageSize));
+ my_ptrdiff_t ipL = ((Uint8*)pageP - (Uint8*)memRoot) / pageSize;
+ Int32 ip = (Int32)ipL;
+ Int32 lim = 1 << (pageBits - 1);
+ assert(ip == ipL && -lim <= ip && ip < lim && ip != -1);
+ PtrI pageI = ip << recBits;
+ assert(pageP == getPageP(pageI));
+ return pageI;
+}
+
+void
+SuperPool::movePages(PageList& pl1, PageList& pl2)
+{
+ const Uint32 recBits = 32 - m_pageBits;
+ if (pl1.m_pageCount != 0) {
+ if (pl2.m_pageCount != 0) {
+ PtrI pageI1 = pl1.m_tailPageI;
+ PtrI pageI2 = pl2.m_headPageI;
+ PageEnt& pe1 = getPageEnt(pageI1);
+ PageEnt& pe2 = getPageEnt(pageI2);
+ pe1.m_nextPageI = pageI2;
+ pe2.m_prevPageI = pageI1;
+ pl1.m_pageCount += pl2.m_pageCount;
+ }
+ } else {
+ pl1 = pl2;
+ }
+ pl2.m_headPageI = pl2.m_tailPageI = RNIL;
+ pl2.m_pageCount = 0;
+}
+
+void
+SuperPool::addHeadPage(PageList& pl, PtrI pageI)
+{
+ PageList pl2(pageI);
+ movePages(pl2, pl);
+ pl = pl2;
+}
+
+void
+SuperPool::addTailPage(PageList& pl, PtrI pageI)
+{
+ PageList pl2(pageI);
+ movePages(pl, pl2);
+}
+
+void
+SuperPool::removePage(PageList& pl, PtrI pageI)
+{
+ PageEnt& pe = getPageEnt(pageI);
+ PtrI pageI1 = pe.m_prevPageI;
+ PtrI pageI2 = pe.m_nextPageI;
+ if (pageI1 != RNIL) {
+ PageEnt& pe1 = getPageEnt(pageI1);
+ pe1.m_nextPageI = pageI2;
+ if (pageI2 != RNIL) {
+ PageEnt& pe2 = getPageEnt(pageI2);
+ pe2.m_prevPageI = pageI1;
+ } else {
+ pl.m_tailPageI = pageI1;
+ }
+ } else {
+ if (pageI2 != RNIL) {
+ PageEnt& pe2 = getPageEnt(pageI2);
+ pe2.m_prevPageI = pageI1;
+ pl.m_headPageI = pageI2;
+ } else {
+ pl.m_headPageI = pl.m_tailPageI = RNIL;
+ }
+ }
+ pe.m_prevPageI = pe.m_nextPageI = RNIL;
+ assert(pl.m_pageCount != 0);
+ pl.m_pageCount--;
+}
+
+void
+SuperPool::setCurrPage(RecInfo& ri, PtrI newPageI)
+{
+ PtrI oldPageI = ri.m_currPageI;
+ if (oldPageI != RNIL) {
+ // copy from cache
+ PageEnt& pe = getPageEnt(oldPageI);
+ pe.m_freeRecI = ri.m_currFreeRecI;
+ pe.m_useCount = ri.m_currUseCount;
+ // add to right list according to "pp2" policy
+ if (pe.m_useCount == 0) {
+ pe.m_pageType = 0;
+ addHeadPage(m_pageList, oldPageI);
+ ri.m_totalRecCount -= ri.m_maxUseCount;
+ } else if (pe.m_useCount < ri.m_maxUseCount) {
+ addHeadPage(ri.m_activeList, oldPageI);
+ } else {
+ addHeadPage(ri.m_fullList, oldPageI);
+ }
+ }
+ if (newPageI != RNIL) {
+ PageEnt& pe = getPageEnt(newPageI);
+ // copy to cache
+ ri.m_currPageI = newPageI;
+ ri.m_currFreeRecI = pe.m_freeRecI;
+ ri.m_currUseCount = pe.m_useCount;
+ // remove from right list
+ if (pe.m_useCount == 0) {
+ removePage(ri.m_freeList, newPageI);
+ } else if (pe.m_useCount < ri.m_maxUseCount) {
+ removePage(ri.m_activeList, newPageI);
+ } else {
+ removePage(ri.m_fullList, newPageI);
+ }
+ } else {
+ ri.m_currPageI = RNIL;
+ ri.m_currFreeRecI = RNIL;
+ ri.m_currUseCount = 0;
+ }
+}
+
+bool
+SuperPool::getAvailPage(RecInfo& ri)
+{
+ PtrI pageI;
+ if ((pageI = ri.m_activeList.m_headPageI) != RNIL ||
+ (pageI = ri.m_freeList.m_headPageI) != RNIL ||
+ (pageI = getFreePage(ri)) != RNIL) {
+ setCurrPage(ri, pageI);
+ return true;
+ }
+ return false;
+}
+
+SuperPool::PtrI
+SuperPool::getFreePage(RecInfo& ri)
+{
+ PtrI pageI;
+ if (m_pageList.m_pageCount != 0) {
+ pageI = m_pageList.m_headPageI;
+ removePage(m_pageList, pageI);
+ } else {
+ pageI = getNewPage();
+ if (pageI == RNIL)
+ return RNIL;
+ }
+ void* pageP = getPageP(pageI);
+ // set up free record list
+ Uint32 maxUseCount = ri.m_maxUseCount;
+ Uint32 recSize = ri.m_recSize;
+ void* recP = (Uint8*)pageP;
+ Uint32 irNext = 1;
+ while (irNext < maxUseCount) {
+ *(Uint32*)recP = pageI | irNext;
+ recP = (Uint8*)recP + recSize;
+ irNext++;
+ }
+ *(Uint32*)recP = RNIL;
+ // add to total record count
+ ri.m_totalRecCount += maxUseCount;
+ // set up new page entry
+ PageEnt& pe = getPageEnt(pageI);
+ new (&pe) PageEnt();
+ pe.m_pageType = ri.m_recType;
+ pe.m_freeRecI = pageI | 0;
+ pe.m_useCount = 0;
+ // set type check bits
+ setCheckBits(pageI, ri.m_recType);
+ // add to record pool free list
+ addHeadPage(ri.m_freeList, pageI);
+ return pageI;
+}
+
+void
+SuperPool::setSizes(size_t initSize, size_t incrSize, size_t maxSize)
+{
+ const Uint32 pageSize = m_pageSize;
+ m_initSize = SP_ALIGN_SIZE(initSize, pageSize);
+ m_incrSize = SP_ALIGN_SIZE(incrSize, pageSize);
+ m_maxSize = SP_ALIGN_SIZE(maxSize, pageSize);
+}
+
+void
+SuperPool::verify(RecInfo& ri)
+{
+ PageList* plList[3] = { &ri.m_freeList, &ri.m_activeList, &ri.m_fullList };
+ for (int i = 0; i < 3; i++) {
+ PageList& pl = *plList[i];
+ unsigned count = 0;
+ PtrI pageI = pl.m_headPageI;
+ while (pageI != RNIL) {
+ PageEnt& pe = getPageEnt(pageI);
+ PtrI pageI1 = pe.m_prevPageI;
+ PtrI pageI2 = pe.m_nextPageI;
+ if (count == 0) {
+ assert(pageI1 == RNIL);
+ } else {
+ assert(pageI1 != RNIL);
+ PageEnt& pe1 = getPageEnt(pageI1);
+ assert(pe1.m_nextPageI == pageI);
+ if (pageI2 != RNIL) {
+ PageEnt& pe2 = getPageEnt(pageI2);
+ assert(pe2.m_prevPageI == pageI);
+ }
+ }
+ pageI = pageI2;
+ count++;
+ }
+ assert(pl.m_pageCount == count);
+ }
+}
+
+// HeapPool
+
+HeapPool::HeapPool(Uint32 pageSize, Uint32 pageBits) :
+ SuperPool(pageSize, pageBits),
+ m_areaHead(),
+ m_currArea(&m_areaHead),
+ m_lastArea(&m_areaHead),
+ m_mallocPart(4)
+{
+}
+
+bool
+HeapPool::init()
+{
+ const Uint32 pageBits = m_pageBits;
+ if (! SuperPool::init())
+ return false;;
+ // allocate page entry array
+ Uint32 peBytes = (1 << pageBits) * sizeof(PageEnt);
+ m_pageEnt = static_cast<PageEnt*>(malloc(peBytes));
+ if (m_pageEnt == 0)
+ return false;
+ memset(m_pageEnt, 0, peBytes);
+ // allocate type check array
+ Uint32 tcWords = 1 << (pageBits - (5 - SP_CHECK_LOG2));
+ m_typeCheck = static_cast<Uint32*>(malloc(tcWords << 2));
+ if (m_typeCheck == 0)
+ return false;
+ memset(m_typeCheck, 0, tcWords << 2);
+ // allocate initial data
+ assert(m_totalSize == 0);
+ if (! allocMoreData(m_initSize))
+ return false;
+ return true;
+}
+
+HeapPool::~HeapPool()
+{
+ free(m_pageEnt);
+ free(m_typeCheck);
+ Area* ap;
+ while ((ap = m_areaHead.m_nextArea) != 0) {
+ m_areaHead.m_nextArea = ap->m_nextArea;
+ free(ap->m_memory);
+ free(ap);
+ }
+}
+
+HeapPool::Area::Area() :
+ m_nextArea(0),
+ m_firstPageI(RNIL),
+ m_currPage(0),
+ m_numPages(0),
+ m_memory(0)
+{
+}
+
+SuperPool::PtrI
+HeapPool::getNewPage()
+{
+ const Uint32 pageSize = m_pageSize;
+ const Uint32 pageBits = m_pageBits;
+ const Uint32 recBits= 32 - pageBits;
+ Area* ap = m_currArea;
+ if (ap->m_currPage == ap->m_numPages) {
+ // area is used up
+ if (ap->m_nextArea == 0) {
+ // todo dynamic increase
+ assert(m_incrSize == 0);
+ return RNIL;
+ }
+ ap = m_currArea = ap->m_nextArea;
+ }
+ assert(ap->m_currPage < ap->m_numPages);
+ PtrI pageI = ap->m_firstPageI;
+ Int32 ip = (Int32)pageI >> recBits;
+ ip += ap->m_currPage;
+ pageI = ip << recBits;
+ ap->m_currPage++;
+ return pageI;
+}
+
+bool
+HeapPool::allocMoreData(size_t size)
+{
+ const Uint32 pageSize = m_pageSize;
+ const Uint32 pageBits = m_pageBits;
+ const Uint32 recBits = 32 - pageBits;
+ const Uint32 incrSize = m_incrSize;
+ const Uint32 incrPages = incrSize / pageSize;
+ const Uint32 mallocPart = m_mallocPart;
+ size = SP_ALIGN_SIZE(size, pageSize);
+ if (incrSize != 0)
+ size = SP_ALIGN_SIZE(size, incrSize);
+ Uint32 needPages = size / pageSize;
+ while (needPages != 0) {
+ Uint32 wantPages = needPages;
+ if (incrPages != 0 && wantPages > incrPages)
+ wantPages = incrPages;
+ Uint32 tryPages = 0;
+ void* p1 = 0;
+ for (Uint32 i = mallocPart; i > 0 && p1 == 0; i--) {
+ // one page is usually wasted due to alignment to memory root
+ tryPages = ((wantPages + 1) * i) / mallocPart;
+ if (tryPages < 2)
+ break;
+ p1 = malloc(pageSize * tryPages);
+ }
+ if (p1 == 0)
+ return false;
+ if (m_memRoot == 0) {
+ // set memory root at first "big" alloc
+ // assume malloc header makes later ip = -1 impossible
+ m_memRoot = p1;
+ }
+ void* p2 = SP_ALIGN_PTR(p1, m_memRoot, pageSize);
+ Uint32 numPages = tryPages - (p1 != p2);
+ my_ptrdiff_t ipL = ((Uint8*)p2 - (Uint8*)m_memRoot) / pageSize;
+ Int32 ip = (Int32)ipL;
+ Int32 lim = 1 << (pageBits - 1);
+ if (! (ip == ipL && -lim <= ip && ip + numPages < lim)) {
+ free(p1);
+ return false;
+ }
+ assert(ip != -1);
+ PtrI pageI = ip << recBits;
+ needPages = (needPages >= numPages ? needPages - numPages : 0);
+ m_totalSize += numPages * pageSize;
+ // allocate new area
+ Area* ap = static_cast<Area*>(malloc(sizeof(Area)));
+ if (ap == 0) {
+ free(p1);
+ return false;
+ }
+ new (ap) Area();
+ ap->m_firstPageI = pageI;
+ ap->m_numPages = numPages;
+ ap->m_memory = p1;
+ m_lastArea->m_nextArea = ap;
+ m_lastArea = ap;
+ }
+ return true;
+}
diff --git a/ndb/src/kernel/vm/SuperPool.hpp b/ndb/src/kernel/vm/SuperPool.hpp
new file mode 100644
index 00000000000..157c75aa0d5
--- /dev/null
+++ b/ndb/src/kernel/vm/SuperPool.hpp
@@ -0,0 +1,561 @@
+/* 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 SUPER_POOL_HPP
+#define SUPER_POOL_HPP
+
+#include <ndb_global.h>
+
+#include <pc.hpp>
+#include <ErrorReporter.hpp>
+
+#define NDB_SP_VERIFY_LEVEL 1
+
+/*
+ * SuperPool - super pool for record pools (abstract class)
+ *
+ * Documents SuperPool and RecordPool<T>.
+ *
+ * GENERAL
+ *
+ * A "super pool" is a shared pool of pages of fixed size. A "record
+ * pool" is a pool of records of fixed size. One super pool instance is
+ * used by any number of record pools to allocate their memory.
+ * A special case is a "page pool" where a record is a simple page,
+ * possibly smaller than super pool page.
+ *
+ * A record pool allocates memory in pages. Thus each used page is
+ * associated with one record pool and one record type. The records on
+ * a page form an array starting at start of page. Thus each record has
+ * an index within the page. Any last partial record which does not fit
+ * on the page is disregarded.
+ *
+ * I-VALUE
+ *
+ * The old "i-p" principle is kept. A reference to a super pool page or
+ * record is stored as an "i-value" from which the record pointer "p" is
+ * computed. In super pool the i-value is a Uint32 with two parts:
+ *
+ * - "ip" index of page within super pool (high pageBits)
+ * - "ir" index of record within page (low recBits)
+ *
+ * The translation between "ip" and page address is described in next
+ * section. Once page address is known, the record address is found
+ * from "ir" in the obvious way.
+ *
+ * The main advantage with i-value is that it can be verified. The
+ * level of verification depends on compile type (release, debug).
+ *
+ * - "v0" minimal sanity check
+ * - "v1" check record type matches page type, see below
+ * - "v2" check record is in use (not yet implemented)
+ *
+ * Another advantage of a 32-bit i-value is that it extends the space of
+ * 32-bit addressable records on a 64-bit platform.
+ *
+ * RNIL is 0xffffff00 and indicates NULL i-value. To avoid hitting RNIL
+ * it is required that pageBits <= 30 and that the maximum value of the
+ * range (2^pageBits-1) is not used.
+ *
+ * MEMORY ROOT
+ *
+ * This super pool requires a "memory root" i.e. a memory address such
+ * that the index of a page "ip" satisfies
+ *
+ * page address = memory root + (signed)ip * page size
+ *
+ * This is possible on most platforms, provided that the memory root and
+ * all pages are either on the heap or on the stack, in order to keep
+ * the size of "ip" reasonably small.
+ *
+ * The cast (signed)ip is done as integer of pageBits bits. "ip" has
+ * same sign bit as i-value "i" so (signed)ip = (Int32)i >> recBits.
+ * The RNIL restriction can be expressed as (signed)ip != -1.
+ *
+ * PAGE ENTRIES
+ *
+ * Each super pool page has a "page entry". It contains:
+ *
+ * - page type
+ * - i-value of first free record on page
+ * - page use count, to see if page can be freed
+ * - pointers (as i-values) to next and previous page in list
+ *
+ * Page entry cannot be stored on the page itself since this prevents
+ * aligning pages to OS block size and the use of BATs (don't ask) for
+ * page pools in NDB. For now the implementation provides an array of
+ * page entries with place for all (2^pageBits) entries.
+ *
+ * PAGE TYPE
+ *
+ * Page type is (in principle) unique to the record pool using the super
+ * pool. It is assigned in record pool constructor. Page type zero
+ * means that the page is free i.e. not allocated to a record pool.
+ *
+ * Each "i-p" conversion checks ("v1") that the record belongs to same
+ * pool as the page. This check is much more common than page or record
+ * allocation. To make it cache effective, there is a separate array of
+ * reduced "type bits" (computed from real type).
+ *
+ * FREE LISTS
+ *
+ * A record is either used or on the free list of the record pool.
+ * A page has a use count i.e. number of used records. When use count
+ * drops to zero the page can be returned to the super pool. This is
+ * not necessarily done at once, or ever.
+ *
+ * To make freeing pages feasible, the record pool free list has two
+ * levels. There are available pages (some free) and a singly linked
+ * free list within the page. A page allocated to record pool is on one
+ * of 4 lists:
+ *
+ * - free page list (all free, available)
+ * - active page list (some free, some used, available)
+ * - full page list (none free)
+ * - current page (list of 1), see below
+ *
+ * Some usage types (temporary pools) may never free records. They pay
+ * a small penalty for the extra overhead.
+ *
+ * RECORD POOL
+ *
+ * A pool of records which allocates its memory from a super pool
+ * instance specified in the constructor. There are 3 basic operations:
+ *
+ * - getPtr - translate i-value to pointer-to-record p
+ * - seize - allocate record
+ * - release - free record
+ *
+ * CURRENT PAGE
+ *
+ * getPtr is a fast computation which does not touch the page. For
+ * seize and release there is an optimization:
+ *
+ * Define "current page" as page of latest seize or release. Its page
+ * entry is cached under record pool instance. The page is removed from
+ * its normal list. Seize and release on current page are fast and
+ * avoid touching the page. The current page is used until
+ *
+ * - seize and current page is full
+ * - release and the page is not current page
+ *
+ * Then the real page entry is updated and the page is added to the
+ * appropriate list, and a new page is made current.
+ *
+ * PAGE POLICY
+ *
+ * Allocating new page to record pool is expensive. Therefore record
+ * pool should not always return empty pages to super pool. There are
+ * two trivial policies, each with problems:
+ *
+ * - "pp1" never return empty page to super pool
+ * - "pp2" always return empty page to super pool
+ *
+ * This implementation uses "pp2" for now. A real policy is implemented
+ * in next version.
+ *
+ * OPEN ISSUES AND LIMITATIONS
+ *
+ * - smarter (virtual) placement of check bits & page entries
+ * - should getPtr etc be inlined? (too much code)
+ * - real page policy
+ * - other implementations (only HeapPool is done)
+ * - super pool list of all record pools, for statistics etc
+ * - access by multiple threads is not supported
+ */
+
+// align size
+#define SP_ALIGN_SIZE(sz, al) \
+ (((sz) + (al) - 1) & ~((al) - 1))
+
+// align pointer relative to base
+#define SP_ALIGN_PTR(p, base, al) \
+ (void*)((Uint8*)(base) + SP_ALIGN_SIZE((Uint8*)(p) - (Uint8*)(base), (al)))
+
+class SuperPool {
+public:
+ // Type of i-value, used to reference both pages and records. Page
+ // index "ip" occupies the high bits. The i-value of a page is same
+ // as i-value of record 0 on the page.
+ typedef Uint32 PtrI;
+
+ // Size and address alignment given as number of bytes (power of 2).
+ STATIC_CONST( SP_ALIGN = 8 );
+
+ // Page entry. Current|y allocated as array of (2^pageBits).
+ struct PageEnt {
+ PageEnt();
+ Uint32 m_pageType;
+ Uint32 m_freeRecI;
+ Uint32 m_useCount;
+ PtrI m_nextPageI;
+ PtrI m_prevPageI;
+ };
+
+ // Number of bits for cache effective type check given as log of 2.
+ // Example: 2 means 4 bits and uses 32k for 2g of 32k pages.
+ STATIC_CONST( SP_CHECK_LOG2 = 2 );
+
+ // Doubly-linked list of pages. There is one free list in super pool
+ // and free, active, full list in each record pool.
+ struct PageList {
+ PageList();
+ PageList(PtrI pageI);
+ PtrI m_headPageI;
+ PtrI m_tailPageI;
+ Uint32 m_pageCount;
+ };
+
+ // Record pool information. Each record pool instance contains one.
+ struct RecInfo {
+ RecInfo(Uint32 recType, Uint32 recSize);
+ const Uint32 m_recType;
+ const Uint32 m_recSize;
+ Uint32 m_maxUseCount; // could be computed
+ Uint32 m_currPageI; // current page
+ Uint32 m_currFreeRecI;
+ Uint32 m_currUseCount;
+ Uint32 m_totalUseCount; // total per pool
+ Uint32 m_totalRecCount;
+ PageList m_freeList;
+ PageList m_activeList;
+ PageList m_fullList;
+ };
+
+ // Constructor. Gives page size in bytes (excluding page header) and
+ // number of bits to use for page index "ip" in i-value.
+ SuperPool(Uint32 pageSize, Uint32 pageBits);
+
+ // Initialize. Must be called after setting sizes or other parameters
+ // and before the pool is used.
+ virtual bool init();
+
+ // Destructor.
+ virtual ~SuperPool() = 0;
+
+ // Translate i-value to page entry.
+ PageEnt& getPageEnt(PtrI pageI);
+
+ // Translate i-value to page address.
+ void* getPageP(PtrI pageI);
+
+ // Translate page address to i-value (unused).
+ PtrI getPageI(void* pageP);
+
+ // Given type, return non-zero reduced type check bits.
+ Uint32 makeCheckBits(Uint32 type);
+
+ // Get type check bits from type check array.
+ Uint32 getCheckBits(PtrI pageI);
+
+ // Set type check bits in type check array.
+ void setCheckBits(PtrI pageI, Uint32 type);
+
+ // Translate i-value to record address.
+ void* getRecP(PtrI recI, RecInfo& ri);
+
+ // Move all pages from second list to end of first list.
+ void movePages(PageList& pl1, PageList& pl2);
+
+ // Add page to beginning of page list.
+ void addHeadPage(PageList& pl, PtrI pageI);
+
+ // Add page to end of page list.
+ void addTailPage(PageList& pl, PtrI pageI);
+
+ // Remove any page from page list.
+ void removePage(PageList& pl, PtrI pageI);
+
+ // Set current page. Previous current page is updated and added to
+ // appropriate list.
+ void setCurrPage(RecInfo& ri, PtrI pageI);
+
+ // Get page with some free records and make it current. Takes head of
+ // active or free list, or else gets free page from super pool.
+ bool getAvailPage(RecInfo& ri);
+
+ // Get free page from super pool and add it to record pool free list.
+ // This is an expensive subroutine of getAvailPage().
+ PtrI getFreePage(RecInfo& ri);
+
+ // Get new free page from the implementation.
+ virtual PtrI getNewPage() = 0;
+
+ // Set 3 size parameters, rounded to page size. If called before
+ // init() then init() allocates the initial size.
+ void setSizes(size_t initSize = 0, size_t incrSize = 0, size_t maxSize = 0);
+
+ const Uint32 m_pageSize;
+ const Uint32 m_pageBits;
+ // implementation must set up these pointers
+ void* m_memRoot;
+ PageEnt* m_pageEnt;
+ Uint32* m_typeCheck;
+ Uint32 m_typeSeq;
+ PageList m_pageList;
+ size_t m_totalSize;
+ size_t m_initSize;
+ size_t m_incrSize;
+ size_t m_maxSize;
+
+ // Debugging.
+ void verify(RecInfo& ri);
+};
+
+inline SuperPool::PageEnt&
+SuperPool::getPageEnt(PtrI pageI)
+{
+ Uint32 ip = pageI >> (32 - m_pageBits);
+ return m_pageEnt[ip];
+}
+
+inline void*
+SuperPool::getPageP(PtrI ptrI)
+{
+ Int32 ip = (Int32)ptrI >> (32 - m_pageBits);
+ my_ptrdiff_t sz = m_pageSize;
+ void* pageP = (Uint8*)m_memRoot + ip * sz;
+ return pageP;
+}
+
+inline Uint32
+SuperPool::makeCheckBits(Uint32 type)
+{
+ Uint32 shift = 1 << SP_CHECK_LOG2;
+ Uint32 mask = (1 << shift) - 1;
+ return 1 + type % mask;
+}
+
+inline Uint32
+SuperPool::getCheckBits(PtrI pageI)
+{
+ Uint32 ip = pageI >> (32 - m_pageBits);
+ Uint32 xp = ip >> (5 - SP_CHECK_LOG2);
+ Uint32 yp = ip & (1 << (5 - SP_CHECK_LOG2)) - 1;
+ Uint32& w = m_typeCheck[xp];
+ Uint32 shift = 1 << SP_CHECK_LOG2;
+ Uint32 mask = (1 << shift) - 1;
+ // get
+ Uint32 bits = (w >> yp * shift) & mask;
+ return bits;
+}
+
+inline void
+SuperPool::setCheckBits(PtrI pageI, Uint32 type)
+{
+ Uint32 ip = pageI >> (32 - m_pageBits);
+ Uint32 xp = ip >> (5 - SP_CHECK_LOG2);
+ Uint32 yp = ip & (1 << (5 - SP_CHECK_LOG2)) - 1;
+ Uint32& w = m_typeCheck[xp];
+ Uint32 shift = 1 << SP_CHECK_LOG2;
+ Uint32 mask = (1 << shift) - 1;
+ // set
+ Uint32 bits = makeCheckBits(type);
+ w &= ~(mask << yp * shift);
+ w |= (bits << yp * shift);
+}
+
+inline void*
+SuperPool::getRecP(PtrI ptrI, RecInfo& ri)
+{
+ const Uint32 recMask = (1 << (32 - m_pageBits)) - 1;
+ PtrI pageI = ptrI & ~recMask;
+#if NDB_SP_VERIFY_LEVEL >= 1
+ Uint32 bits1 = getCheckBits(pageI);
+ Uint32 bits2 = makeCheckBits(ri.m_recType);
+ assert(bits1 == bits2);
+#endif
+ void* pageP = getPageP(pageI);
+ Uint32 ir = ptrI & recMask;
+ void* recP = (Uint8*)pageP + ir * ri.m_recSize;
+ return recP;
+}
+
+/*
+ * HeapPool - SuperPool on heap (concrete class)
+ *
+ * A super pool based on malloc with memory root on the heap. This
+ * pool type has 2 realistic uses:
+ *
+ * - a small pool with only initial malloc and pageBits set to match
+ * - the big pool from which all heap allocations are done
+ *
+ * A "smart" malloc may break "ip" limit by using different VM areas for
+ * different sized requests. For this reason malloc is done in units of
+ * increment size if possible. Memory root is set to start of first
+ * malloc.
+ */
+
+class HeapPool : public SuperPool {
+public:
+ // Describes malloc area. The areas are kept in singly linked list.
+ // There is a list head and pointers to current and last area.
+ struct Area {
+ Area();
+ Area* m_nextArea;
+ PtrI m_firstPageI;
+ Uint32 m_currPage;
+ Uint32 m_numPages;
+ void* m_memory;
+ };
+
+ // Constructor.
+ HeapPool(Uint32 pageSize, Uint32 pageBits);
+
+ // Initialize.
+ virtual bool init();
+
+ // Destructor.
+ virtual ~HeapPool();
+
+ // Use malloc to allocate more.
+ bool allocMoreData(size_t size);
+
+ // Get new page from current area.
+ virtual PtrI getNewPage();
+
+ // List of malloc areas.
+ Area m_areaHead;
+ Area* m_currArea;
+ Area* m_lastArea;
+
+ // Fraction of malloc size to try if cannot get all in one.
+ Uint32 m_mallocPart;
+};
+
+/*
+ * RecordPool - record pool using one super pool instance (template)
+ *
+ * Documented under SuperPool. Satisfies ArrayPool interface.
+ */
+
+template <class T>
+class RecordPool {
+public:
+ // Constructor.
+ RecordPool(SuperPool& superPool);
+
+ // Destructor.
+ ~RecordPool();
+
+ // Update pointer ptr.p according to i-value ptr.i.
+ void getPtr(Ptr<T>& ptr);
+
+ // Allocate record from the pool.
+ bool seize(Ptr<T>& ptr);
+
+ // Return record to the pool.
+ void release(Ptr<T>& ptr);
+
+ // todo variants of basic methods
+
+ // Return all pages to super pool. The force flag is required if
+ // there are any used records.
+ void free(bool force);
+
+ SuperPool& m_superPool;
+ SuperPool::RecInfo m_recInfo;
+};
+
+template <class T>
+inline
+RecordPool<T>::RecordPool(SuperPool& superPool) :
+ m_superPool(superPool),
+ m_recInfo(1 + superPool.m_typeSeq++, sizeof(T))
+{
+ SuperPool::RecInfo& ri = m_recInfo;
+ assert(sizeof(T) == SP_ALIGN_SIZE(sizeof(T), sizeof(Uint32)));
+ Uint32 maxUseCount = superPool.m_pageSize / sizeof(T);
+ Uint32 sizeLimit = 1 << (32 - superPool.m_pageBits);
+ if (maxUseCount >= sizeLimit)
+ maxUseCount = sizeLimit;
+ ri.m_maxUseCount = maxUseCount;
+}
+
+template <class T>
+inline
+RecordPool<T>::~RecordPool()
+{
+ free(true);
+}
+
+template <class T>
+inline void
+RecordPool<T>::getPtr(Ptr<T>& ptr)
+{
+ void* recP = m_superPool.getRecP(ptr.i, m_recInfo);
+ ptr.p = static_cast<T*>(recP);
+}
+
+template <class T>
+inline bool
+RecordPool<T>::seize(Ptr<T>& ptr)
+{
+ SuperPool& sp = m_superPool;
+ SuperPool::RecInfo& ri = m_recInfo;
+ if (ri.m_currFreeRecI != RNIL || sp.getAvailPage(ri)) {
+ SuperPool::PtrI recI = ri.m_currFreeRecI;
+ void* recP = sp.getRecP(recI, ri);
+ ri.m_currFreeRecI = *(Uint32*)recP;
+ Uint32 useCount = ri.m_currUseCount;
+ assert(useCount < ri.m_maxUseCount);
+ ri.m_currUseCount = useCount + 1;
+ ri.m_totalUseCount++;
+ ptr.i = recI;
+ ptr.p = static_cast<T*>(recP);
+ return true;
+ }
+ return false;
+}
+
+template <class T>
+inline void
+RecordPool<T>::release(Ptr<T>& ptr)
+{
+ SuperPool& sp = m_superPool;
+ SuperPool::RecInfo& ri = m_recInfo;
+ const Uint32 recMask = (1 << (32 - sp.m_pageBits)) - 1;
+ SuperPool::PtrI recI = ptr.i;
+ SuperPool::PtrI pageI = recI & ~recMask;
+ if (pageI != ri.m_currPageI) {
+ sp.setCurrPage(ri, pageI);
+ }
+ void* recP = sp.getRecP(recI, ri);
+ *(Uint32*)recP = ri.m_currFreeRecI;
+ ri.m_currFreeRecI = recI;
+ Uint32 useCount = ri.m_currUseCount;
+ assert(useCount != 0);
+ ri.m_currUseCount = useCount - 1;
+ ri.m_totalUseCount--;
+ ptr.i = RNIL;
+ ptr.p = 0;
+}
+
+template <class T>
+inline void
+RecordPool<T>::free(bool force)
+{
+ SuperPool& sp = m_superPool;
+ SuperPool::RecInfo& ri = m_recInfo;
+ sp.setCurrPage(ri, RNIL);
+ assert(force || ri.m_totalUseCount == 0);
+ sp.movePages(sp.m_pageList, ri.m_freeList);
+ sp.movePages(sp.m_pageList, ri.m_activeList);
+ sp.movePages(sp.m_pageList, ri.m_fullList);
+ ri.m_totalRecCount = 0;
+}
+
+#endif
diff --git a/ndb/src/kernel/vm/TimeQueue.cpp b/ndb/src/kernel/vm/TimeQueue.cpp
index 56988c2e3da..0b620c75d52 100644
--- a/ndb/src/kernel/vm/TimeQueue.cpp
+++ b/ndb/src/kernel/vm/TimeQueue.cpp
@@ -19,7 +19,6 @@
#include <GlobalData.hpp>
#include <FastScheduler.hpp>
#include <VMSignal.hpp>
-#include <Error.hpp>
static const int MAX_TIME_QUEUE_VALUE = 32000;
@@ -70,7 +69,7 @@ TimeQueue::insert(Signal* signal, BlockNumber bnr,
if (regShortIndex == 0){
theShortQueue[0].copy_struct = newEntry.copy_struct;
} else if (regShortIndex >= MAX_NO_OF_SHORT_TQ - 1) {
- ERROR_SET(ecError, ERROR_TIME_QUEUE_SHORT,
+ ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_SHORT,
"Too many in Short Time Queue", "TimeQueue.C" );
} else {
for (i = 0; i < regShortIndex; i++) {
@@ -99,7 +98,7 @@ TimeQueue::insert(Signal* signal, BlockNumber bnr,
if (regLongIndex == 0) {
theLongQueue[0].copy_struct = newEntry.copy_struct;
} else if (regLongIndex >= MAX_NO_OF_LONG_TQ - 1) {
- ERROR_SET(ecError, ERROR_TIME_QUEUE_LONG,
+ ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_LONG,
"Too many in Long Time Queue", "TimeQueue.C" );
} else {
for (i = 0; i < regLongIndex; i++) {
@@ -124,7 +123,7 @@ TimeQueue::insert(Signal* signal, BlockNumber bnr,
}
globalData.theLongTQIndex = regLongIndex + 1;
} else {
- ERROR_SET(ecError, ERROR_TIME_QUEUE_DELAY,
+ ERROR_SET(ecError, NDBD_EXIT_TIME_QUEUE_DELAY,
"Too long delay for Time Queue", "TimeQueue.C" );
}
}
@@ -194,7 +193,7 @@ TimeQueue::getIndex()
Uint32 retValue = globalData.theFirstFreeTQIndex;
globalData.theFirstFreeTQIndex = (Uint32)theFreeIndex[retValue];
if (retValue >= MAX_NO_OF_TQ)
- ERROR_SET(fatal, ERROR_TIME_QUEUE_INDEX,
+ ERROR_SET(fatal, NDBD_EXIT_TIME_QUEUE_INDEX,
"Index out of range", "TimeQueue.C" );
return retValue;
}
diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp
index ba929b7ea7a..f315918b871 100644
--- a/ndb/src/kernel/vm/TransporterCallback.cpp
+++ b/ndb/src/kernel/vm/TransporterCallback.cpp
@@ -33,11 +33,34 @@
#include <NdbOut.hpp>
#include "DataBuffer.hpp"
+
/**
* The instance
*/
SectionSegmentPool g_sectionSegmentPool;
+struct ConnectionError
+{
+ enum TransporterError err;
+ const char *text;
+};
+
+static const ConnectionError connectionError[] =
+{
+ { TE_NO_ERROR, "No error"},
+ { TE_SHM_UNABLE_TO_CREATE_SEGMENT, "Unable to create shared memory segment"},
+ { (enum TransporterError) -1, "No connection error message available (please report a bug)"}
+};
+
+const char *lookupConnectionError(Uint32 err)
+{
+ int i= 0;
+ while ((Uint32)connectionError[i].err != err &&
+ (Uint32)connectionError[i].err != -1)
+ i++;
+ return connectionError[i].text;
+}
+
bool
import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len){
/**
@@ -305,41 +328,61 @@ checkJobBuffer() {
}
void
-reportError(void * callbackObj, NodeId nodeId, TransporterError errorCode){
+reportError(void * callbackObj, NodeId nodeId,
+ TransporterError errorCode, const char *info)
+{
#ifdef DEBUG_TRANSPORTER
- char buf[255];
- sprintf(buf, "reportError (%d, 0x%x)", nodeId, errorCode);
- ndbout << buf << endl;
+ ndbout_c("reportError (%d, 0x%x) %s", nodeId, errorCode, info ? info : "")
#endif
- if(errorCode == TE_SIGNAL_LOST_SEND_BUFFER_FULL){
- ErrorReporter::handleError(ecError,
- ERR_PROGRAMERROR,
- "Signal lost, send buffer full",
- __FILE__,
- NST_ErrorHandler);
+ DBUG_ENTER("reportError");
+ DBUG_PRINT("info",("nodeId %d errorCode: 0x%x info: %s",
+ nodeId, errorCode, info));
+
+ switch (errorCode)
+ {
+ case TE_SIGNAL_LOST_SEND_BUFFER_FULL:
+ {
+ char msg[64];
+ snprintf(msg, sizeof(msg), "Remote note id %d.%s%s", nodeId,
+ info ? " " : "", info ? info : "");
+ ErrorReporter::handleError(NDBD_EXIT_SIGNAL_LOST_SEND_BUFFER_FULL,
+ msg, __FILE__, NST_ErrorHandler);
}
-
- if(errorCode == TE_SIGNAL_LOST){
- ErrorReporter::handleError(ecError,
- ERR_PROGRAMERROR,
- "Signal lost (unknown reason)",
- __FILE__,
- NST_ErrorHandler);
+ case TE_SIGNAL_LOST:
+ {
+ char msg[64];
+ snprintf(msg, sizeof(msg), "Remote node id %d,%s%s", nodeId,
+ info ? " " : "", info ? info : "");
+ ErrorReporter::handleError(NDBD_EXIT_SIGNAL_LOST,
+ msg, __FILE__, NST_ErrorHandler);
}
-
- if(errorCode & 0x8000){
+ case TE_SHM_IPC_PERMANENT:
+ {
+ char msg[128];
+ snprintf(msg, sizeof(msg),
+ "Remote node id %d.%s%s",
+ nodeId, info ? " " : "", info ? info : "");
+ ErrorReporter::handleError(NDBD_EXIT_CONNECTION_SETUP_FAILED,
+ msg, __FILE__, NST_ErrorHandler);
+ }
+ default:
+ break;
+ }
+
+ if(errorCode & TE_DO_DISCONNECT){
reportDisconnect(callbackObj, nodeId, errorCode);
}
- Signal signal;
+ SignalT<3> signalT;
+ Signal &signal= *(Signal*)&signalT;
memset(&signal.header, 0, sizeof(signal.header));
- if(errorCode & 0x8000)
- signal.theData[0] = EventReport::TransporterError;
+ if(errorCode & TE_DO_DISCONNECT)
+ signal.theData[0] = NDB_LE_TransporterError;
else
- signal.theData[0] = EventReport::TransporterWarning;
+ signal.theData[0] = NDB_LE_TransporterWarning;
signal.theData[1] = nodeId;
signal.theData[2] = errorCode;
@@ -348,6 +391,8 @@ reportError(void * callbackObj, NodeId nodeId, TransporterError errorCode){
signal.header.theSendersSignalId = 0;
signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
+
+ DBUG_VOID_RETURN;
}
/**
@@ -357,13 +402,14 @@ void
reportSendLen(void * callbackObj,
NodeId nodeId, Uint32 count, Uint64 bytes){
- Signal signal;
+ SignalT<3> signalT;
+ Signal &signal= *(Signal*)&signalT;
memset(&signal.header, 0, sizeof(signal.header));
signal.header.theLength = 3;
signal.header.theSendersSignalId = 0;
signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- signal.theData[0] = EventReport::SendBytesStatistic;
+ signal.theData[0] = NDB_LE_SendBytesStatistic;
signal.theData[1] = nodeId;
signal.theData[2] = (bytes/count);
globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
@@ -376,13 +422,14 @@ void
reportReceiveLen(void * callbackObj,
NodeId nodeId, Uint32 count, Uint64 bytes){
- Signal signal;
+ SignalT<3> signalT;
+ Signal &signal= *(Signal*)&signalT;
memset(&signal.header, 0, sizeof(signal.header));
signal.header.theLength = 3;
signal.header.theSendersSignalId = 0;
signal.header.theSendersBlockRef = numberToRef(0, globalData.ownId);
- signal.theData[0] = EventReport::ReceiveBytesStatistic;
+ signal.theData[0] = NDB_LE_ReceiveBytesStatistic;
signal.theData[1] = nodeId;
signal.theData[2] = (bytes/count);
globalScheduler.execute(&signal, JBA, CMVMI, GSN_EVENT_REP);
@@ -395,7 +442,8 @@ reportReceiveLen(void * callbackObj,
void
reportConnect(void * callbackObj, NodeId nodeId){
- Signal signal;
+ SignalT<1> signalT;
+ Signal &signal= *(Signal*)&signalT;
memset(&signal.header, 0, sizeof(signal.header));
signal.header.theLength = 1;
@@ -412,7 +460,10 @@ reportConnect(void * callbackObj, NodeId nodeId){
void
reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 errNo){
- Signal signal;
+ DBUG_ENTER("reportDisconnect");
+
+ SignalT<sizeof(DisconnectRep)/4> signalT;
+ Signal &signal= *(Signal*)&signalT;
memset(&signal.header, 0, sizeof(signal.header));
signal.header.theLength = DisconnectRep::SignalLength;
@@ -425,6 +476,8 @@ reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 errNo){
rep->err = errNo;
globalScheduler.execute(&signal, JBA, CMVMI, GSN_DISCONNECT_REP);
+
+ DBUG_VOID_RETURN;
}
void
@@ -452,3 +505,8 @@ SignalLoggerManager::printSegmentedSection(FILE * output,
putc('\n', output);
}
+void
+transporter_recv_from(void * callbackObj, NodeId nodeId){
+ globalData.m_nodeInfo[nodeId].m_heartbeat_cnt= 0;
+ return;
+}
diff --git a/ndb/src/kernel/vm/VMSignal.hpp b/ndb/src/kernel/vm/VMSignal.hpp
index 9111ee7949c..33f8a9f25c0 100644
--- a/ndb/src/kernel/vm/VMSignal.hpp
+++ b/ndb/src/kernel/vm/VMSignal.hpp
@@ -42,6 +42,16 @@ struct NodeReceiverGroup {
NodeBitmask m_nodes;
};
+template <unsigned T> struct SignalT
+{
+ SignalHeader header;
+ SegmentedSectionPtr m_sectionPtr[3];
+ union {
+ Uint32 theData[T];
+ Uint64 dummyAlign;
+ };
+};
+
/**
* class used for passing argumentes to blocks
*/
@@ -78,10 +88,16 @@ public:
#define VMS_DATA_SIZE \
(MAX_ATTRIBUTES_IN_TABLE + MAX_TUPLE_SIZE_IN_WORDS + MAX_KEY_SIZE_IN_WORDS)
+#if VMS_DATA_SIZE > 8192
+#error "VMSignal buffer is too small"
+#endif
+
SignalHeader header; // 28 bytes
SegmentedSectionPtr m_sectionPtr[3];
- Uint32 theData[25+VMS_DATA_SIZE]; // 2048 32-bit words -> 8K Bytes
-
+ union {
+ Uint32 theData[8192]; // 8192 32-bit words -> 32K Bytes
+ Uint64 dummyAlign;
+ };
void garbage_register();
};
diff --git a/ndb/src/kernel/vm/WatchDog.cpp b/ndb/src/kernel/vm/WatchDog.cpp
index 23475a478d3..c80317e1725 100644
--- a/ndb/src/kernel/vm/WatchDog.cpp
+++ b/ndb/src/kernel/vm/WatchDog.cpp
@@ -95,39 +95,40 @@ WatchDog::run(){
globalData.incrementWatchDogCounter(0);
alerts = 0;
} else {
+ const char *last_stuck_action;
alerts++;
- ndbout << "Ndb kernel is stuck in: ";
switch (oldIPValue) {
case 1:
- ndbout << "Job Handling" << endl;
+ last_stuck_action = "Job Handling";
break;
case 2:
- ndbout << "Scanning Timers" << endl;
+ last_stuck_action = "Scanning Timers";
break;
case 3:
- ndbout << "External I/O" << endl;
+ last_stuck_action = "External I/O";
break;
case 4:
- ndbout << "Print Job Buffers at crash" << endl;
+ last_stuck_action = "Print Job Buffers at crash";
break;
case 5:
- ndbout << "Checking connections" << endl;
+ last_stuck_action = "Checking connections";
break;
case 6:
- ndbout << "Performing Send" << endl;
+ last_stuck_action = "Performing Send";
break;
case 7:
- ndbout << "Polling for Receive" << endl;
+ last_stuck_action = "Polling for Receive";
break;
case 8:
- ndbout << "Performing Receive" << endl;
+ last_stuck_action = "Performing Receive";
break;
default:
- ndbout << "Unknown place" << endl;
+ last_stuck_action = "Unknown place";
break;
}//switch
+ ndbout << "Ndb kernel is stuck in: " << last_stuck_action << endl;
if(alerts == 3){
- shutdownSystem();
+ shutdownSystem(last_stuck_action);
}
}
}
@@ -135,11 +136,10 @@ WatchDog::run(){
}
void
-WatchDog::shutdownSystem(){
+WatchDog::shutdownSystem(const char *last_stuck_action){
- ErrorReporter::handleError(ecError,
- ERR_PROGRAMERROR,
- "WatchDog terminate",
+ ErrorReporter::handleError(NDBD_EXIT_WATCHDOG_TERMINATE,
+ last_stuck_action,
__FILE__,
NST_Watchdog);
}
diff --git a/ndb/src/kernel/vm/WatchDog.hpp b/ndb/src/kernel/vm/WatchDog.hpp
index 4b44b1a96a2..65b23dafdb1 100644
--- a/ndb/src/kernel/vm/WatchDog.hpp
+++ b/ndb/src/kernel/vm/WatchDog.hpp
@@ -50,7 +50,7 @@ private:
bool theStop;
void run();
- void shutdownSystem();
+ void shutdownSystem(const char *last_stuck_action);
};
#endif // WatchDog_H
diff --git a/ndb/src/kernel/vm/ndbd_malloc.cpp b/ndb/src/kernel/vm/ndbd_malloc.cpp
new file mode 100644
index 00000000000..4bfccf828fc
--- /dev/null
+++ b/ndb/src/kernel/vm/ndbd_malloc.cpp
@@ -0,0 +1,63 @@
+/* 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 "ndbd_malloc.hpp"
+#include <NdbMem.h>
+
+//#define TRACE_MALLOC
+#ifdef TRACE_MALLOC
+#include <stdio.h>
+#endif
+
+static void xxx(size_t size, size_t *s_m, size_t *s_k, size_t *s_b)
+{
+ *s_m = size/1024/1024;
+ *s_k = (size - *s_m*1024*1024)/1024;
+ *s_b = size - *s_m*1024*1024-*s_k*1024;
+}
+
+static Uint64 g_allocated_memory;
+void *ndbd_malloc(size_t size)
+{
+ void *p = NdbMem_Allocate(size);
+ if (p)
+ {
+ g_allocated_memory += size;
+#ifdef TRACE_MALLOC
+ {
+ size_t s_m, s_k, s_b;
+ xxx(size, &s_m, &s_k, &s_b);
+ fprintf(stderr, "%p malloc(%um %uk %ub)", p, s_m, s_k, s_b);
+ xxx(g_allocated_memory, &s_m, &s_k, &s_b);
+ fprintf(stderr, "\t\ttotal(%um %uk %ub)\n", s_m, s_k, s_b);
+ }
+#endif
+ }
+ return p;
+}
+
+void ndbd_free(void *p, size_t size)
+{
+ NdbMem_Free(p);
+ if (p)
+ {
+ g_allocated_memory -= size;
+#ifdef TRACE_MALLOC
+ fprintf(stderr, "%p free(%d)\n", p, size);
+#endif
+ }
+}
diff --git a/ndb/src/kernel/error/ErrorMessages.hpp b/ndb/src/kernel/vm/ndbd_malloc.hpp
index 38c8eec636b..136e9f0c372 100644
--- a/ndb/src/kernel/error/ErrorMessages.hpp
+++ b/ndb/src/kernel/vm/ndbd_malloc.hpp
@@ -14,9 +14,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef ERROR_MESSAGES_H
-#define ERROR_MESSAGES_H
+#ifndef NDBD_MALLOC_H
+#define NDBD_MALLOC_H
-const char* lookupErrorMessage(int faultId);
+/**
+ * common memory allocation function for ndbd kernel
+ */
+void *ndbd_malloc(size_t size);
+void ndbd_free(void *p, size_t size);
-#endif
+#endif
diff --git a/ndb/src/kernel/vm/pc.hpp b/ndb/src/kernel/vm/pc.hpp
index 2d745d26b1c..95839c48e4e 100644
--- a/ndb/src/kernel/vm/pc.hpp
+++ b/ndb/src/kernel/vm/pc.hpp
@@ -90,7 +90,7 @@
* @param limit max no of records in rec
* @param rec pointer to first record in an array of records
*/
-#define ptrCheckGuard(ptr, limit, rec) {\
+#define ptrCheckGuardErr(ptr, limit, rec, error) {\
UintR TxxzLimit; \
TxxzLimit = (limit); \
UintR TxxxPtr; \
@@ -99,33 +99,39 @@
if (TxxxPtr < (TxxzLimit)) { \
; \
} else { \
- progError(__LINE__, ERR_POINTER_NOTINRANGE, __FILE__); \
+ progError(__LINE__, error, __FILE__); \
}}
-
#define ptrAss(ptr, rec) ptr.p = &rec[ptr.i]
#define ptrNull(ptr) ptr.p = NULL
-#define ptrGuard(ptr) if (ptr.p == NULL) \
- progError(__LINE__, ERR_POINTER_NOTINRANGE, __FILE__)
-#define arrGuard(ind, size) if ((ind) >= (size)) \
- progError(__LINE__, ERR_INDEX_NOTINRANGE, __FILE__)
+#define ptrGuardErr(ptr, error) if (ptr.p == NULL) \
+ progError(__LINE__, error, __FILE__)
+#define arrGuardErr(ind, size, error) if ((ind) >= (size)) \
+ progError(__LINE__, error, __FILE__)
#else
#define ptrCheck(ptr, limit, rec) ptr.p = &rec[ptr.i]
-#define ptrCheckGuard(ptr, limit, rec) ptr.p = &rec[ptr.i]
+#define ptrCheckGuardErr(ptr, limit, rec, error) ptr.p = &rec[ptr.i]
#define ptrAss(ptr, rec) ptr.p = &rec[ptr.i]
#define ptrNull(ptr) ptr.p = NULL
-#define ptrGuard(ptr)
-#define arrGuard(ind, size)
+#define ptrGuardErr(ptr, error)
+#define arrGuardErr(ind, size, error)
#endif
+#define ptrCheckGuard(ptr, limit, rec) \
+ ptrCheckGuardErr(ptr, limit, rec, NDBD_EXIT_POINTER_NOTINRANGE)
+#define ptrGuard(ptr) ptrGuardErr(ptr, NDBD_EXIT_POINTER_NOTINRANGE)
+#define arrGuard(ind, size) arrGuardErr(ind, size, NDBD_EXIT_INDEX_NOTINRANGE)
+
// -------- ERROR INSERT MACROS -------
#ifdef ERROR_INSERT
#define ERROR_INSERT_VARIABLE UintR cerrorInsert
#define ERROR_INSERTED(x) (cerrorInsert == (x))
+#define ERROR_INSERTED_CLEAR(x) (cerrorInsert == (x) ? (cerrorInsert = 0, true) : false)
#define SET_ERROR_INSERT_VALUE(x) cerrorInsert = x
#define CLEAR_ERROR_INSERT_VALUE cerrorInsert = 0
#else
#define ERROR_INSERT_VARIABLE typedef void * cerrorInsert // Will generate compiler error if used
#define ERROR_INSERTED(x) false
+#define ERROR_INSERTED_CLEAR(x) false
#define SET_ERROR_INSERT_VALUE(x)
#define CLEAR_ERROR_INSERT_VALUE
#endif
@@ -197,34 +203,31 @@
#define ndbassert(check) \
if((check)){ \
} else { \
- progError(__LINE__, ERR_NDBREQUIRE, __FILE__); \
- }
-
-#define ndbrequire(check) \
- if((check)){ \
- } else { \
- progError(__LINE__, ERR_NDBREQUIRE, __FILE__); \
- }
+ progError(__LINE__, NDBD_EXIT_NDBASSERT, __FILE__); \
+ }
#else
#define ndbassert(check)
+#endif
-#define ndbrequire(check) \
+#define ndbrequireErr(check, error) \
if((check)){ \
} else { \
- progError(__LINE__, ERR_NDBREQUIRE, __FILE__); \
- }
-#endif
+ progError(__LINE__, error, __FILE__); \
+ }
+
+#define ndbrequire(check) \
+ ndbrequireErr(check, NDBD_EXIT_NDBREQUIRE)
#define CRASH_INSERTION(errorType) \
if (!ERROR_INSERTED((errorType))) { \
} else { \
- progError(__LINE__, ERR_ERROR_INSERT, __FILE__); \
+ progError(__LINE__, NDBD_EXIT_ERROR_INSERT, __FILE__); \
}
#define CRASH_INSERTION2(errorNum, condition) \
if (!(ERROR_INSERTED(errorNum) && condition)) { \
} else { \
- progError(__LINE__, ERR_ERROR_INSERT, __FILE__); \
+ progError(__LINE__, NDBD_EXIT_ERROR_INSERT, __FILE__); \
}
#define MEMCOPY_PAGE(to, from, page_size_in_bytes) \
diff --git a/ndb/src/kernel/vm/testSuperPool.cpp b/ndb/src/kernel/vm/testSuperPool.cpp
new file mode 100644
index 00000000000..194b3a43fa0
--- /dev/null
+++ b/ndb/src/kernel/vm/testSuperPool.cpp
@@ -0,0 +1,220 @@
+#if 0
+make -f Makefile -f - testSuperPool <<'_eof_'
+testSuperPool: testSuperPool.cpp libkernel.a
+ $(CXXCOMPILE) -o $@ $@.cpp libkernel.a -L../../common/util/.libs -lgeneral
+_eof_
+exit $?
+#endif
+
+/* 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 "SuperPool.hpp"
+#include <NdbOut.hpp>
+
+template <Uint32 sz>
+struct A {
+ Uint32 a[sz];
+ void fill() {
+ Uint32 c = 0;
+ for (Uint32 i = 0; i + 1 < sz; i++) {
+ a[i] = random();
+ c = (c << 1) ^ a[i];
+ }
+ a[sz - 1] = c;
+ }
+ void check() {
+ Uint32 c = 0;
+ for (Uint32 i = 0; i + 1 < sz; i++) {
+ c = (c << 1) ^ a[i];
+ }
+ assert(a[sz - 1] == c);
+ }
+};
+
+static Uint32
+urandom(Uint32 n)
+{
+ return (Uint32)random() % n;
+}
+
+static Uint32
+random_coprime(Uint32 n)
+{
+ Uint32 prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
+ Uint32 count = sizeof(prime) / sizeof(prime[0]);
+ while (1) {
+ Uint32 i = urandom(count);
+ if (n % prime[i] != 0)
+ return prime[i];
+ }
+}
+
+static int
+cmpPtrI(const void* a, const void* b)
+{
+ Ptr<const void> u = *(Ptr<const void>*)a;
+ Ptr<const void> v = *(Ptr<const void>*)b;
+ return u.i < v.i ? -1 : u.i > v.i ? +1 : 0;
+}
+
+static int
+cmpPtrP(const void* a, const void* b)
+{
+ Ptr<const void> u = *(Ptr<const void>*)a;
+ Ptr<const void> v = *(Ptr<const void>*)b;
+ return u.p < v.p ? -1 : u.p > v.p ? +1 : 0;
+}
+
+static Uint32 loopcount = 3;
+
+template <Uint32 sz>
+void
+sp_test(SuperPool& sp)
+{
+ typedef A<sz> T;
+ RecordPool<T> rp(sp);
+ SuperPool::RecInfo& ri = rp.m_recInfo;
+ Uint32 pageCount = sp.m_totalSize / sp.m_pageSize;
+ Uint32 perPage = rp.m_recInfo.m_maxUseCount;
+ Uint32 perPool = perPage * pageCount;
+ ndbout << "pages=" << pageCount << " perpage=" << perPage << " perpool=" << perPool << endl;
+ Ptr<T>* ptrList = new Ptr<T> [perPool];
+ memset(ptrList, 0x1f, perPool * sizeof(Ptr<T>));
+ Uint32 loop;
+ for (loop = 0; loop < loopcount; loop++) {
+ ndbout << "loop " << loop << endl;
+ Uint32 i, j;
+ // seize all
+ ndbout << "seize all" << endl;
+ for (i = 0; i < perPool + 1; i++) {
+ j = i;
+ sp.verify(ri);
+ Ptr<T> ptr1 = { 0, RNIL };
+ if (! rp.seize(ptr1))
+ break;
+ // write value
+ ptr1.p->fill();
+ ptr1.p->check();
+ // verify getPtr
+ Ptr<T> ptr2 = { 0, ptr1.i };
+ rp.getPtr(ptr2);
+ assert(ptr1.i == ptr2.i && ptr1.p == ptr2.p);
+ // save
+ ptrList[j] = ptr1;
+ }
+ assert(i == perPool);
+ assert(ri.m_totalUseCount == perPool && ri.m_totalRecCount == perPool);
+ sp.verify(ri);
+ // check duplicates
+ {
+ Ptr<T>* ptrList2 = new Ptr<T> [perPool];
+ memcpy(ptrList2, ptrList, perPool * sizeof(Ptr<T>));
+ qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrI);
+ for (i = 1; i < perPool; i++)
+ assert(ptrList2[i - 1].i != ptrList2[i].i);
+ qsort(ptrList2, perPool, sizeof(Ptr<T>), cmpPtrP);
+ for (i = 1; i < perPool; i++)
+ assert(ptrList2[i - 1].p != ptrList2[i].p);
+ delete [] ptrList2;
+ }
+ // release all in various orders
+ ndbout << "release all" << endl;
+ Uint32 coprime = random_coprime(perPool);
+ for (i = 0; i < perPool; i++) {
+ sp.verify(ri);
+ switch (loop % 3) {
+ case 0: // ascending
+ j = i;
+ break;
+ case 1: // descending
+ j = perPool - 1 - i;
+ break;
+ case 2: // pseudo-random
+ j = (coprime * i) % perPool;
+ break;
+ }
+ Ptr<T>& ptr = ptrList[j];
+ assert(ptr.i != RNIL && ptr.p != 0);
+ ptr.p->check();
+ rp.release(ptr);
+ assert(ptr.i == RNIL && ptr.p == 0);
+ }
+ sp.setCurrPage(ri, RNIL);
+ assert(ri.m_totalUseCount == 0 && ri.m_totalRecCount == 0);
+ sp.verify(ri);
+ // seize/release at random
+ ndbout << "seize/release at random" << endl;
+ for (i = 0; i < loopcount * perPool; i++) {
+ j = urandom(perPool);
+ Ptr<T>& ptr = ptrList[j];
+ if (ptr.i == RNIL) {
+ rp.seize(ptr);
+ ptr.p->fill();
+ } else {
+ ptr.p->check();
+ rp.release(ptr);
+ }
+ }
+ ndbout << "used " << ri.m_totalUseCount << endl;
+ sp.verify(ri);
+ // release all
+ ndbout << "release all" << endl;
+ for (i = 0; i < perPool; i++) {
+ j = i;
+ Ptr<T>& ptr = ptrList[j];
+ if (ptr.i != RNIL) {
+ ptr.p->check();
+ rp.release(ptr);
+ }
+ }
+ sp.setCurrPage(ri, RNIL);
+ assert(ri.m_totalUseCount == 0 && ri.m_totalRecCount == 0);
+ sp.verify(ri);
+ }
+ // done
+ delete [] ptrList;
+}
+
+static Uint32 pageCount = 99;
+static Uint32 pageSize = 32768;
+static Uint32 pageBits = 15;
+
+const Uint32 sz1 = 3, sz2 = 4, sz3 = 53, sz4 = 424, sz5 = 5353;
+
+template void sp_test<sz1>(SuperPool& sp);
+template void sp_test<sz2>(SuperPool& sp);
+template void sp_test<sz3>(SuperPool& sp);
+template void sp_test<sz4>(SuperPool& sp);
+template void sp_test<sz5>(SuperPool& sp);
+
+int
+main()
+{
+ HeapPool sp(pageSize, pageBits);
+ sp.setSizes(pageCount * pageSize);
+ if (! sp.init())
+ assert(false);
+ Uint16 s = (Uint16)getpid();
+ srandom(s);
+ ndbout << "rand " << s << endl;
+ sp_test<sz1>(sp);
+ sp_test<sz2>(sp);
+ sp_test<sz3>(sp);
+ sp_test<sz4>(sp);
+ sp_test<sz5>(sp);
+ return 0;
+}
diff --git a/ndb/src/mgmapi/LocalConfig.cpp b/ndb/src/mgmapi/LocalConfig.cpp
index 0265f982df3..75ad8b40a1f 100644
--- a/ndb/src/mgmapi/LocalConfig.cpp
+++ b/ndb/src/mgmapi/LocalConfig.cpp
@@ -27,7 +27,9 @@ LocalConfig::LocalConfig(){
bool
LocalConfig::init(const char *connectString,
- const char *fileName) {
+ const char *fileName)
+{
+ DBUG_ENTER("LocalConfig::init");
/**
* Escalation:
* 1. Check connectString
@@ -38,21 +40,25 @@ LocalConfig::init(const char *connectString,
* 6. Check defaultConnectString
*/
+ _ownNodeId= 0;
+
//1. Check connectString
if(connectString != 0 && connectString[0] != 0){
if(readConnectString(connectString, "connect string")){
- return true;
- }
- return false;
+ if (ids.size())
+ DBUG_RETURN(true);
+ // only nodeid given, continue to find hosts
+ } else
+ DBUG_RETURN(false);
}
//2. Check given filename
if (fileName && strlen(fileName) > 0) {
bool fopenError;
if(readFile(fileName, fopenError)){
- return true;
+ DBUG_RETURN(true);
}
- return false;
+ DBUG_RETURN(false);
}
//3. Check environment variable
@@ -60,9 +66,9 @@ LocalConfig::init(const char *connectString,
if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
strlen(buf) != 0){
if(readConnectString(buf, "NDB_CONNECTSTRING")){
- return true;
+ DBUG_RETURN(true);
}
- return false;
+ DBUG_RETURN(false);
}
//4. Check Ndb.cfg in NDB_HOME
@@ -71,9 +77,9 @@ LocalConfig::init(const char *connectString,
char *buf= NdbConfig_NdbCfgName(1 /*true*/);
NdbAutoPtr<char> tmp_aptr(buf);
if(readFile(buf, fopenError))
- return true;
+ DBUG_RETURN(true);
if (!fopenError)
- return false;
+ DBUG_RETURN(false);
}
//5. Check Ndb.cfg in cwd
@@ -82,9 +88,9 @@ LocalConfig::init(const char *connectString,
char *buf= NdbConfig_NdbCfgName(0 /*false*/);
NdbAutoPtr<char> tmp_aptr(buf);
if(readFile(buf, fopenError))
- return true;
+ DBUG_RETURN(true);
if (!fopenError)
- return false;
+ DBUG_RETURN(false);
}
//7. Check
@@ -92,12 +98,12 @@ LocalConfig::init(const char *connectString,
char buf[256];
BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_PORT);
if(readConnectString(buf, "default connect string"))
- return true;
+ DBUG_RETURN(true);
}
setError(0, "");
- return false;
+ DBUG_RETURN(false);
}
LocalConfig::~LocalConfig(){
@@ -142,6 +148,7 @@ const char *nodeIdTokens[] = {
const char *hostNameTokens[] = {
"host://%[^:]:%i",
"host=%[^:]:%i",
+ "mgmd=%[^:]:%i",
"%[^:^=^ ]:%i",
"%s %i",
0
@@ -207,36 +214,22 @@ LocalConfig::parseString(const char * connectString, BaseString &err){
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;
tok = strtok_r(NULL, ";,", &for_strtok)) {
if (tok[0] == '#') continue;
- if (!b_nodeId) // only one nodeid definition allowed
- if (b_nodeId = parseNodeId(tok))
+ if (!_ownNodeId) // only one nodeid definition allowed
+ if (parseNodeId(tok))
continue;
- if (found_other = parseHostName(tok))
+ if (parseHostName(tok))
continue;
- if (found_other = parseFileName(tok))
+ if (parseFileName(tok))
continue;
err.assfmt("Unexpected entry: \"%s\"", tok);
return false;
}
- if (b_nodeId && !found_other)
- {
- BaseString tmp;
- tmp.assfmt("host=localhost:%s", NDB_PORT);
- if(parseHostName(tmp.c_str()))
- return true;
-
- err.appfmt("Missing host/file name extry in \"%s\"", connectString);
- return false;
- }
-
return true;
}
diff --git a/ndb/src/mgmapi/Makefile.am b/ndb/src/mgmapi/Makefile.am
index 2f2fb407e46..efe1b8ea2d5 100644
--- a/ndb/src/mgmapi/Makefile.am
+++ b/ndb/src/mgmapi/Makefile.am
@@ -1,7 +1,7 @@
noinst_LTLIBRARIES = libmgmapi.la
-libmgmapi_la_SOURCES = mgmapi.cpp mgmapi_configuration.cpp LocalConfig.cpp
+libmgmapi_la_SOURCES = mgmapi.cpp ndb_logevent.cpp mgmapi_configuration.cpp LocalConfig.cpp ../kernel/error/ndbd_exit_codes.c
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index fc9e5a20f4e..4428b158b6b 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -22,10 +22,12 @@
#include <NdbSleep.h>
#include <NdbTCP.h>
-#include "mgmapi.h"
-#include "mgmapi_debug.h"
+#include <mgmapi.h>
+#include <mgmapi_internal.h>
+#include <mgmapi_debug.h>
#include "mgmapi_configuration.hpp"
#include <socket_io.h>
+#include <version.h>
#include <NdbOut.hpp>
#include <SocketServer.hpp>
@@ -33,8 +35,8 @@
#include <Parser.hpp>
#include <OutputStream.hpp>
#include <InputStream.hpp>
-#include <Base64.hpp>
+#include <base64.h>
#define MGM_CMD(name, fun, desc) \
{ name, \
@@ -101,6 +103,10 @@ struct ndb_mgm_handle {
FILE* logfile;
#endif
FILE *errstream;
+ char *m_name;
+ int mgmd_version_major;
+ int mgmd_version_minor;
+ int mgmd_version_build;
};
#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
@@ -153,8 +159,9 @@ ndb_mgm_create_handle()
h->socket = NDB_INVALID_SOCKET;
h->read_timeout = 50000;
h->write_timeout = 100;
- h->cfg_i = 0;
+ h->cfg_i = -1;
h->errstream = stdout;
+ h->m_name = 0;
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
@@ -165,14 +172,28 @@ ndb_mgm_create_handle()
h->logfile = 0;
#endif
- DBUG_PRINT("exit",("ret: %lx", h));
+ h->mgmd_version_major= -1;
+ h->mgmd_version_minor= -1;
+ h->mgmd_version_build= -1;
+
+ DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h));
DBUG_RETURN(h);
}
extern "C"
+void
+ndb_mgm_set_name(NdbMgmHandle handle, const char *name)
+{
+ my_free(handle->m_name, MYF(MY_ALLOW_ZERO_PTR));
+ handle->m_name= my_strdup(name, MYF(MY_WME));
+}
+
+extern "C"
int
ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
{
+ DBUG_ENTER("ndb_mgm_set_connectstring");
+ DBUG_PRINT("info", ("handle=0x%x", (UintPtr)handle));
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig;
if (!handle->cfg.init(mgmsrv, 0) ||
@@ -180,12 +201,12 @@ ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
{
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig;
- handle->cfg.init(0, 0); /* reset the LocalCongig */
+ handle->cfg.init(0, 0); /* reset the LocalConfig */
SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
- return -1;
+ DBUG_RETURN(-1);
}
- handle->cfg_i= 0;
- return 0;
+ handle->cfg_i= -1;
+ DBUG_RETURN(0);
}
/**
@@ -197,9 +218,12 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
{
DBUG_ENTER("ndb_mgm_destroy_handle");
if(!handle)
- return;
- DBUG_PRINT("enter",("*handle: %lx", *handle));
-
+ DBUG_VOID_RETURN;
+ DBUG_PRINT("info", ("handle=0x%x", (UintPtr)(* handle)));
+ /**
+ * important! only disconnect if connected
+ * other code relies on this
+ */
if((* handle)->connected){
ndb_mgm_disconnect(* handle);
}
@@ -210,6 +234,7 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
}
#endif
(*handle)->cfg.~LocalConfig();
+ my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR));
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
* handle = 0;
DBUG_VOID_RETURN;
@@ -307,8 +332,11 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
out.println("%s: %s", name, val_s.c_str());
break;
case PropertiesType_Properties:
+ DBUG_PRINT("info",("Ignoring PropertiesType_Properties."));
/* Ignore */
break;
+ default:
+ DBUG_PRINT("info",("Ignoring PropertiesType: %d.",t));
}
}
#ifdef MGMAPI_LOG
@@ -324,17 +352,30 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
ParserDummy session(handle->socket);
Parser_t parser(command_reply, in, true, true, true);
-#if 1
const Properties* p = parser.parse(ctx, session);
if (p == NULL){
- /**
- * Print some info about why the parser returns NULL
- */
- DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
- ctx.m_status, ctx.m_currentToken));
- //ndbout << " status=" << ctx.m_status << ", curr="
- //<< ctx.m_currentToken << endl;
- }
+ if(!ndb_mgm_is_connected(handle)) {
+ DBUG_RETURN(NULL);
+ }
+ else
+ {
+ if(ctx.m_status==Parser_t::Eof
+ || ctx.m_status==Parser_t::NoLine)
+ {
+ ndb_mgm_disconnect(handle);
+ DBUG_RETURN(NULL);
+ }
+ /**
+ * Print some info about why the parser returns NULL
+ */
+ fprintf(handle->errstream,
+ "Error in mgm protocol parser. cmd: >%s< status: %d curr: %s\n",
+ cmd, (Uint32)ctx.m_status,
+ (ctx.m_currentToken)?ctx.m_currentToken:"NULL");
+ DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
+ ctx.m_status, ctx.m_currentToken));
+ }
+ }
#ifdef MGMAPI_LOG
else {
/**
@@ -344,9 +385,26 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
}
#endif
DBUG_RETURN(p);
-#else
- DBUG_RETURN(parser.parse(ctx, session));
-#endif
+}
+
+/**
+ * Returns true if connected
+ */
+extern "C"
+int ndb_mgm_is_connected(NdbMgmHandle handle)
+{
+ if(!handle)
+ return 0;
+
+ if(handle->connected)
+ {
+ if(Ndb_check_socket_hup(handle->socket))
+ {
+ handle->connected= 0;
+ NDB_CLOSE_SOCKET(handle->socket);
+ }
+ }
+ return handle->connected;
}
/**
@@ -360,6 +418,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
CHECK_HANDLE(handle, -1);
+ DBUG_ENTER("ndb_mgm_connect");
#ifdef MGMAPI_LOG
/**
* Open the log file
@@ -389,6 +448,13 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
}
if (sockfd != NDB_INVALID_SOCKET)
break;
+#ifndef DBUG_OFF
+ {
+ char buf[1024];
+ DBUG_PRINT("info",("Unable to connect with connect string: %s",
+ cfg.makeConnectString(buf,sizeof(buf))));
+ }
+#endif
if (verbose > 0) {
char buf[1024];
fprintf(handle->errstream, "Unable to connect with connect string: %s\n",
@@ -402,7 +468,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
cfg.makeConnectString(buf,sizeof(buf)));
if (verbose == -2)
fprintf(handle->errstream, ", failed.\n");
- return -1;
+ DBUG_RETURN(-1);
}
if (verbose == -1) {
fprintf(handle->errstream, "Retrying every %d seconds",
@@ -433,7 +499,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
handle->socket = sockfd;
handle->connected = 1;
- return 0;
+ DBUG_RETURN(0);
}
/**
@@ -621,7 +687,11 @@ ndb_mgm_get_status(NdbMgmHandle handle)
out.println("");
char buf[1024];
- in.gets(buf, sizeof(buf));
+ if(!in.gets(buf, sizeof(buf)))
+ {
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
+ return NULL;
+ }
if(buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
@@ -630,7 +700,11 @@ ndb_mgm_get_status(NdbMgmHandle handle)
return NULL;
}
- in.gets(buf, sizeof(buf));
+ if(!in.gets(buf, sizeof(buf)))
+ {
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
+ return NULL;
+ }
if(buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
@@ -653,7 +727,13 @@ ndb_mgm_get_status(NdbMgmHandle handle)
malloc(sizeof(ndb_mgm_cluster_state)+
noOfNodes*(sizeof(ndb_mgm_node_state)+sizeof("000.000.000.000#")));
- state->hostname= 0;
+ if(!state)
+ {
+ SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
+ "Allocating ndb_mgm_cluster_state");
+ return NULL;
+ }
+
state->no_of_nodes= noOfNodes;
ndb_mgm_node_state * ptr = &state->node_states[0];
int nodeId = 0;
@@ -663,7 +743,13 @@ ndb_mgm_get_status(NdbMgmHandle handle)
}
i = -1; ptr--;
for(; i<noOfNodes; ){
- in.gets(buf, sizeof(buf));
+ if(!in.gets(buf, sizeof(buf)))
+ {
+ free(state);
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
+ "Probably disconnected");
+ return NULL;
+ }
tmp.assign(buf);
if(tmp.trim() == ""){
@@ -773,37 +859,81 @@ ndb_mgm_stop(NdbMgmHandle handle, int no_of_nodes, const int * node_list)
return ndb_mgm_stop2(handle, no_of_nodes, node_list, 0);
}
-
extern "C"
-int
+int
ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
int abort)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop2");
- const ParserRow<ParserDummy> stop_reply[] = {
+ int disconnect;
+ return ndb_mgm_stop3(handle, no_of_nodes, node_list, abort, &disconnect);
+}
+
+
+extern "C"
+int
+ndb_mgm_stop3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
+ int abort, int *disconnect)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_stop3");
+ const ParserRow<ParserDummy> stop_reply_v1[] = {
+ MGM_CMD("stop reply", NULL, ""),
+ MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+ const ParserRow<ParserDummy> stop_reply_v2[] = {
MGM_CMD("stop reply", NULL, ""),
MGM_ARG("stopped", Int, Optional, "No of stopped nodes"),
MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_ARG("disconnect", Int, Mandatory, "Need to disconnect"),
MGM_END()
};
+
CHECK_HANDLE(handle, -1);
CHECK_CONNECTED(handle, -1);
- if(no_of_nodes < 0){
+ if(handle->mgmd_version_build==-1)
+ {
+ char verstr[50];
+ if(!ndb_mgm_get_version(handle,
+ &(handle->mgmd_version_major),
+ &(handle->mgmd_version_minor),
+ &(handle->mgmd_version_build),
+ sizeof(verstr),
+ verstr))
+ {
+ return -1;
+ }
+ }
+ int use_v2= ((handle->mgmd_version_major==5)
+ && (
+ (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
+ ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
+ ||(handle->mgmd_version_minor>1)
+ )
+ )
+ || (handle->mgmd_version_major>5);
+
+ if(no_of_nodes < -1){
SET_ERROR(handle, NDB_MGM_ILLEGAL_NUMBER_OF_NODES,
"Negative number of nodes requested to stop");
return -1;
}
Uint32 stoppedNoOfNodes = 0;
- if(no_of_nodes == 0){
+ if(no_of_nodes <= 0){
/**
- * All database nodes should be stopped
+ * All nodes should be stopped (all or just db)
*/
Properties args;
args.put("abort", abort);
+ if(use_v2)
+ args.put("stop", (no_of_nodes==-1)?"mgm,db":"db");
const Properties *reply;
- reply = ndb_mgm_call(handle, stop_reply, "stop all", &args);
+ if(use_v2)
+ reply = ndb_mgm_call(handle, stop_reply_v2, "stop all", &args);
+ else
+ reply = ndb_mgm_call(handle, stop_reply_v1, "stop all", &args);
CHECK_REPLY(reply, -1);
if(!reply->get("stopped", &stoppedNoOfNodes)){
@@ -812,6 +942,10 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
delete reply;
return -1;
}
+ if(use_v2)
+ reply->get("disconnect", (Uint32*)disconnect);
+ else
+ *disconnect= 0;
BaseString result;
reply->get("result", result);
if(strcmp(result.c_str(), "Ok") != 0) {
@@ -837,7 +971,11 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
args.put("abort", abort);
const Properties *reply;
- reply = ndb_mgm_call(handle, stop_reply, "stop", &args);
+ if(use_v2)
+ reply = ndb_mgm_call(handle, stop_reply_v2, "stop v2", &args);
+ else
+ reply = ndb_mgm_call(handle, stop_reply_v1, "stop", &args);
+
CHECK_REPLY(reply, stoppedNoOfNodes);
if(!reply->get("stopped", &stoppedNoOfNodes)){
SET_ERROR(handle, NDB_MGM_STOP_FAILED,
@@ -845,6 +983,10 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
delete reply;
return -1;
}
+ if(use_v2)
+ reply->get("disconnect", (Uint32*)disconnect);
+ else
+ *disconnect= 0;
BaseString result;
reply->get("result", result);
if(strcmp(result.c_str(), "Ok") != 0) {
@@ -858,20 +1000,69 @@ ndb_mgm_stop2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
extern "C"
int
+ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
+ return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
+}
+
+extern "C"
+int
ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
int initial, int nostart, int abort)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart2");
+ int disconnect;
+
+ return ndb_mgm_restart3(handle, no_of_nodes, node_list, initial, nostart,
+ abort, &disconnect);
+}
+
+extern "C"
+int
+ndb_mgm_restart3(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
+ int initial, int nostart, int abort, int *disconnect)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart3");
Uint32 restarted = 0;
- const ParserRow<ParserDummy> restart_reply[] = {
+ const ParserRow<ParserDummy> restart_reply_v1[] = {
MGM_CMD("restart reply", NULL, ""),
MGM_ARG("result", String, Mandatory, "Error message"),
MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
MGM_END()
};
+ const ParserRow<ParserDummy> restart_reply_v2[] = {
+ MGM_CMD("restart reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_ARG("restarted", Int, Optional, "No of restarted nodes"),
+ MGM_ARG("disconnect", Int, Optional, "Disconnect to apply"),
+ MGM_END()
+ };
+
CHECK_HANDLE(handle, -1);
CHECK_CONNECTED(handle, -1);
-
+
+ if(handle->mgmd_version_build==-1)
+ {
+ char verstr[50];
+ if(!ndb_mgm_get_version(handle,
+ &(handle->mgmd_version_major),
+ &(handle->mgmd_version_minor),
+ &(handle->mgmd_version_build),
+ sizeof(verstr),
+ verstr))
+ {
+ return -1;
+ }
+ }
+ int use_v2= ((handle->mgmd_version_major==5)
+ && (
+ (handle->mgmd_version_minor==0 && handle->mgmd_version_build>=21)
+ ||(handle->mgmd_version_minor==1 && handle->mgmd_version_build>=12)
+ ||(handle->mgmd_version_minor>1)
+ )
+ )
+ || (handle->mgmd_version_major>5);
+
if(no_of_nodes < 0){
SET_ERROR(handle, NDB_MGM_RESTART_FAILED,
"Restart requested of negative number of nodes");
@@ -886,7 +1077,7 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
const Properties *reply;
const int timeout = handle->read_timeout;
handle->read_timeout= 5*60*1000; // 5 minutes
- reply = ndb_mgm_call(handle, restart_reply, "restart all", &args);
+ reply = ndb_mgm_call(handle, restart_reply_v1, "restart all", &args);
handle->read_timeout= timeout;
CHECK_REPLY(reply, -1);
@@ -922,7 +1113,10 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
const Properties *reply;
const int timeout = handle->read_timeout;
handle->read_timeout= 5*60*1000; // 5 minutes
- reply = ndb_mgm_call(handle, restart_reply, "restart node", &args);
+ if(use_v2)
+ reply = ndb_mgm_call(handle, restart_reply_v2, "restart node v2", &args);
+ else
+ reply = ndb_mgm_call(handle, restart_reply_v1, "restart node", &args);
handle->read_timeout= timeout;
if(reply != NULL) {
BaseString result;
@@ -933,81 +1127,78 @@ ndb_mgm_restart2(NdbMgmHandle handle, int no_of_nodes, const int * node_list,
return -1;
}
reply->get("restarted", &restarted);
+ if(use_v2)
+ reply->get("disconnect", (Uint32*)disconnect);
+ else
+ *disconnect= 0;
delete reply;
}
return restarted;
}
-extern "C"
-int
-ndb_mgm_restart(NdbMgmHandle handle, int no_of_nodes, const int *node_list)
-{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_restart");
- return ndb_mgm_restart2(handle, no_of_nodes, node_list, 0, 0, 0);
-}
-
-static const char *clusterlog_level_names[]=
+static const char *clusterlog_severity_names[]=
{ "enabled", "debug", "info", "warning", "error", "critical", "alert" };
-struct ndb_mgm_clusterlog_levels
+struct ndb_mgm_event_severities
{
const char* name;
- enum ndb_mgm_clusterlog_level level;
-} clusterlog_levels[] = {
- { clusterlog_level_names[0], NDB_MGM_CLUSTERLOG_ON },
- { clusterlog_level_names[1], NDB_MGM_CLUSTERLOG_DEBUG },
- { clusterlog_level_names[2], NDB_MGM_CLUSTERLOG_INFO },
- { clusterlog_level_names[3], NDB_MGM_CLUSTERLOG_WARNING },
- { clusterlog_level_names[4], NDB_MGM_CLUSTERLOG_ERROR },
- { clusterlog_level_names[5], NDB_MGM_CLUSTERLOG_CRITICAL },
- { clusterlog_level_names[6], NDB_MGM_CLUSTERLOG_ALERT },
- { "all", NDB_MGM_CLUSTERLOG_ALL },
- { 0, NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL },
+ enum ndb_mgm_event_severity severity;
+} clusterlog_severities[] = {
+ { clusterlog_severity_names[0], NDB_MGM_EVENT_SEVERITY_ON },
+ { clusterlog_severity_names[1], NDB_MGM_EVENT_SEVERITY_DEBUG },
+ { clusterlog_severity_names[2], NDB_MGM_EVENT_SEVERITY_INFO },
+ { clusterlog_severity_names[3], NDB_MGM_EVENT_SEVERITY_WARNING },
+ { clusterlog_severity_names[4], NDB_MGM_EVENT_SEVERITY_ERROR },
+ { clusterlog_severity_names[5], NDB_MGM_EVENT_SEVERITY_CRITICAL },
+ { clusterlog_severity_names[6], NDB_MGM_EVENT_SEVERITY_ALERT },
+ { "all", NDB_MGM_EVENT_SEVERITY_ALL },
+ { 0, NDB_MGM_ILLEGAL_EVENT_SEVERITY },
};
extern "C"
-ndb_mgm_clusterlog_level
-ndb_mgm_match_clusterlog_level(const char * name)
+ndb_mgm_event_severity
+ndb_mgm_match_event_severity(const char * name)
{
if(name == 0)
- return NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
+ return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
- for(int i = 0; clusterlog_levels[i].name !=0 ; i++)
- if(strcasecmp(name, clusterlog_levels[i].name) == 0)
- return clusterlog_levels[i].level;
+ for(int i = 0; clusterlog_severities[i].name !=0 ; i++)
+ if(strcasecmp(name, clusterlog_severities[i].name) == 0)
+ return clusterlog_severities[i].severity;
- return NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
+ return NDB_MGM_ILLEGAL_EVENT_SEVERITY;
}
extern "C"
const char *
-ndb_mgm_get_clusterlog_level_string(enum ndb_mgm_clusterlog_level level)
-{
- int i= (int)level;
- if (i >= 0 && i < (int)NDB_MGM_CLUSTERLOG_ALL)
- return clusterlog_level_names[i];
- for(i = (int)NDB_MGM_CLUSTERLOG_ALL; clusterlog_levels[i].name != 0; i++)
- if(clusterlog_levels[i].level == level)
- return clusterlog_levels[i].name;
+ndb_mgm_get_event_severity_string(enum ndb_mgm_event_severity severity)
+{
+ int i= (int)severity;
+ if (i >= 0 && i < (int)NDB_MGM_EVENT_SEVERITY_ALL)
+ return clusterlog_severity_names[i];
+ for(i = (int)NDB_MGM_EVENT_SEVERITY_ALL; clusterlog_severities[i].name != 0; i++)
+ if(clusterlog_severities[i].severity == severity)
+ return clusterlog_severities[i].name;
return 0;
}
extern "C"
-unsigned int *
-ndb_mgm_get_logfilter(NdbMgmHandle handle)
+const unsigned int *
+ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_logfilter");
- static Uint32 enabled[(int)NDB_MGM_CLUSTERLOG_ALL] = {0,0,0,0,0,0,0};
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
+ static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
+ {0,0,0,0,0,0,0};
const ParserRow<ParserDummy> getinfo_reply[] = {
MGM_CMD("clusterlog", NULL, ""),
- MGM_ARG(clusterlog_level_names[0], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[1], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[2], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[3], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[4], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[5], Int, Mandatory, ""),
- MGM_ARG(clusterlog_level_names[6], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[0], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[1], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[2], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[3], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[4], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[5], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_severity_names[6], Int, Mandatory, ""),
};
CHECK_HANDLE(handle, NULL);
CHECK_CONNECTED(handle, NULL);
@@ -1017,20 +1208,21 @@ ndb_mgm_get_logfilter(NdbMgmHandle handle)
reply = ndb_mgm_call(handle, getinfo_reply, "get info clusterlog", &args);
CHECK_REPLY(reply, NULL);
- for(int i=0; i < (int)NDB_MGM_CLUSTERLOG_ALL; i++) {
- reply->get(clusterlog_level_names[i], &enabled[i]);
+ for(int i=0; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
+ reply->get(clusterlog_severity_names[i], &enabled[i]);
}
return enabled;
}
extern "C"
int
-ndb_mgm_filter_clusterlog(NdbMgmHandle handle,
- enum ndb_mgm_clusterlog_level level,
- int enable,
- struct ndb_mgm_reply* /*reply*/)
+ndb_mgm_set_clusterlog_severity_filter(NdbMgmHandle handle,
+ enum ndb_mgm_event_severity severity,
+ int enable,
+ struct ndb_mgm_reply* /*reply*/)
{
- SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_filter_clusterlog");
+ SET_ERROR(handle, NDB_MGM_NO_ERROR,
+ "Executing: ndb_mgm_set_clusterlog_severity_filter");
const ParserRow<ParserDummy> filter_reply[] = {
MGM_CMD("set logfilter reply", NULL, ""),
MGM_ARG("result", String, Mandatory, "Error message"),
@@ -1041,7 +1233,7 @@ ndb_mgm_filter_clusterlog(NdbMgmHandle handle,
CHECK_CONNECTED(handle, -1);
Properties args;
- args.put("level", level);
+ args.put("level", severity);
args.put("enable", enable);
const Properties *reply;
@@ -1077,8 +1269,8 @@ struct ndb_mgm_event_categories
{ "DEBUG", NDB_MGM_EVENT_CATEGORY_DEBUG },
{ "INFO", NDB_MGM_EVENT_CATEGORY_INFO },
{ "ERROR", NDB_MGM_EVENT_CATEGORY_ERROR },
- { "GREP", NDB_MGM_EVENT_CATEGORY_GREP },
{ "BACKUP", NDB_MGM_EVENT_CATEGORY_BACKUP },
+ { "CONGESTION", NDB_MGM_EVENT_CATEGORY_CONGESTION },
{ 0, NDB_MGM_ILLEGAL_EVENT_CATEGORY }
};
@@ -1110,13 +1302,13 @@ ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
extern "C"
int
-ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle handle, int nodeId,
+ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
enum ndb_mgm_event_category cat,
int level,
struct ndb_mgm_reply* /*reply*/)
{
SET_ERROR(handle, NDB_MGM_NO_ERROR,
- "Executing: ndb_mgm_set_loglevel_clusterlog");
+ "Executing: ndb_mgm_set_clusterlog_loglevel");
const ParserRow<ParserDummy> clusterlog_reply[] = {
MGM_CMD("set cluster loglevel reply", NULL, ""),
MGM_ARG("result", String, Mandatory, "Error message"),
@@ -1135,7 +1327,7 @@ ndb_mgm_set_loglevel_clusterlog(NdbMgmHandle handle, int nodeId,
"set cluster loglevel", &args);
CHECK_REPLY(reply, -1);
- DBUG_ENTER("ndb_mgm_set_loglevel_clusterlog");
+ DBUG_ENTER("ndb_mgm_set_clusterlog_loglevel");
DBUG_PRINT("enter",("node=%d, category=%d, level=%d", nodeId, cat, level));
BaseString result;
@@ -1185,9 +1377,9 @@ ndb_mgm_set_loglevel_node(NdbMgmHandle handle, int nodeId,
return 0;
}
-extern "C"
int
-ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
+ndb_mgm_listen_event_internal(NdbMgmHandle handle, const int filter[],
+ int parsable)
{
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_listen_event");
const ParserRow<ParserDummy> stat_reply[] = {
@@ -1209,6 +1401,9 @@ ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
}
Properties args;
+
+ if (parsable)
+ args.put("parsable", parsable);
{
BaseString tmp;
for(int i = 0; filter[i] != 0; i += 2){
@@ -1225,11 +1420,21 @@ ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
handle->socket = tmp;
- CHECK_REPLY(reply, -1);
+ if(reply == NULL) {
+ close(sockfd);
+ CHECK_REPLY(reply, -1);
+ }
return sockfd;
}
extern "C"
+int
+ndb_mgm_listen_event(NdbMgmHandle handle, const int filter[])
+{
+ return ndb_mgm_listen_event_internal(handle,filter,0);
+}
+
+extern "C"
int
ndb_mgm_get_stat_port(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
{
@@ -1719,11 +1924,15 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
} while(start < len);
if(buf64 == 0)
break;
-
+
+ void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1)));
+ const int res = base64_decode(buf64, len-1, tmp_data);
+ delete[] buf64;
UtilBuffer tmp;
- const int res = base64_decode(buf64, len-1, tmp);
- delete[] buf64;
- if(res != 0){
+ tmp.append((void *) tmp_data, res);
+ free(tmp_data);
+ if (res < 0)
+ {
fprintf(handle->errstream, "Failed to decode buffer\n");
break;
}
@@ -1736,7 +1945,7 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) {
}
delete prop;
- return (ndb_mgm_configuration*)cvf.m_cfg;
+ return (ndb_mgm_configuration*)cvf.getConfigValues();
} while(0);
delete prop;
@@ -1773,13 +1982,19 @@ ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
extern "C"
int ndb_mgm_get_connected_port(NdbMgmHandle handle)
{
- return handle->cfg.ids[handle->cfg_i].port;
+ if (handle->cfg_i >= 0)
+ return handle->cfg.ids[handle->cfg_i].port;
+ else
+ return 0;
}
extern "C"
const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
{
- return handle->cfg.ids[handle->cfg_i].name.c_str();
+ if (handle->cfg_i >= 0)
+ return handle->cfg.ids[handle->cfg_i].name.c_str();
+ else
+ return 0;
}
extern "C"
@@ -1790,7 +2005,8 @@ const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz
extern "C"
int
-ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
+ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype,
+ int log_event)
{
CHECK_HANDLE(handle, 0);
CHECK_CONNECTED(handle, 0);
@@ -1808,9 +2024,13 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
args.put("password", "mysqld");
args.put("public key", "a public key");
args.put("endian", (endian_check.c[sizeof(long)-1])?"big":"little");
+ if (handle->m_name)
+ args.put("name", handle->m_name);
+ args.put("log_event", log_event);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("get nodeid reply", NULL, ""),
+ MGM_ARG("error_code", Int, Optional, "Error code"),
MGM_ARG("nodeid", Int, Optional, "Error message"),
MGM_ARG("result", String, Mandatory, "Error message"),
MGM_END()
@@ -1823,14 +2043,16 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
nodeid= -1;
do {
const char * buf;
- if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ if (!prop->get("result", &buf) || strcmp(buf, "Ok") != 0)
+ {
const char *hostname= ndb_mgm_get_connected_host(handle);
unsigned port= ndb_mgm_get_connected_port(handle);
BaseString err;
+ Uint32 error_code= NDB_MGM_ALLOCID_ERROR;
err.assfmt("Could not alloc node id at %s port %d: %s",
hostname, port, buf);
- setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
- err.c_str());
+ prop->get("error_code", &error_code);
+ setError(handle, error_code, __LINE__, err.c_str());
break;
}
Uint32 _nodeid;
@@ -1893,9 +2115,9 @@ ndb_mgm_set_int_parameter(NdbMgmHandle handle,
CHECK_CONNECTED(handle, 0);
Properties args;
- args.put("node: ", node);
- args.put("param: ", param);
- args.put("value: ", value);
+ args.put("node", node);
+ args.put("param", param);
+ args.put("value", value);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("set parameter reply", NULL, ""),
@@ -1932,9 +2154,9 @@ ndb_mgm_set_int64_parameter(NdbMgmHandle handle,
CHECK_CONNECTED(handle, 0);
Properties args;
- args.put("node: ", node);
- args.put("param: ", param);
- args.put("value: ", value);
+ args.put("node", node);
+ args.put("param", param);
+ args.put("value", value);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("set parameter reply", NULL, ""),
@@ -1975,9 +2197,9 @@ ndb_mgm_set_string_parameter(NdbMgmHandle handle,
CHECK_CONNECTED(handle, 0);
Properties args;
- args.put("node: ", node);
- args.put("parameter: ", param);
- args.put("value: ", value);
+ args.put("node", node);
+ args.put("parameter", param);
+ args.put("value", value);
const ParserRow<ParserDummy> reply[]= {
MGM_CMD("set parameter reply", NULL, ""),
@@ -2083,4 +2305,246 @@ ndb_mgm_check_connection_error:
return -1;
}
+extern "C"
+int
+ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int value,
+ struct ndb_mgm_reply* mgmreply){
+ DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("node1", node1);
+ args.put("node2", node2);
+ args.put("param", param);
+ args.put("value", (Uint32)value);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("set connection parameter reply", NULL, ""),
+ MGM_ARG("message", String, Mandatory, "Error Message"),
+ MGM_ARG("result", String, Mandatory, "Status Result"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "set connection parameter", &args);
+ CHECK_REPLY(prop, -1);
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ fprintf(handle->errstream, "ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ delete prop;
+ DBUG_RETURN(res);
+}
+
+extern "C"
+int
+ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int *value,
+ struct ndb_mgm_reply* mgmreply){
+ DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
+ CHECK_HANDLE(handle, -1);
+ CHECK_CONNECTED(handle, -2);
+
+ Properties args;
+ args.put("node1", node1);
+ args.put("node2", node2);
+ args.put("param", param);
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("get connection parameter reply", NULL, ""),
+ MGM_ARG("value", Int, Mandatory, "Current Value"),
+ MGM_ARG("result", String, Mandatory, "Result"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get connection parameter", &args);
+ CHECK_REPLY(prop, -3);
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ fprintf(handle->errstream, "ERROR Message: %s\n", buf);
+ break;
+ }
+ res= 0;
+ } while(0);
+
+ if(!prop->get("value",(Uint32*)value)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ res = -4;
+ }
+
+ delete prop;
+ DBUG_RETURN(res);
+}
+
+extern "C"
+NDB_SOCKET_TYPE
+ndb_mgm_convert_to_transporter(NdbMgmHandle *handle)
+{
+ NDB_SOCKET_TYPE s;
+
+ CHECK_HANDLE((*handle), NDB_INVALID_SOCKET);
+ CHECK_CONNECTED((*handle), NDB_INVALID_SOCKET);
+
+ (*handle)->connected= 0; // we pretend we're disconnected
+ s= (*handle)->socket;
+
+ SocketOutputStream s_output(s);
+ s_output.println("transporter connect");
+ s_output.println("");
+
+ ndb_mgm_destroy_handle(handle); // set connected=0, so won't disconnect
+
+ return s;
+}
+
+extern "C"
+Uint32
+ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle)
+{
+ Uint32 nodeid=0;
+
+ DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("get mgmd nodeid reply", NULL, ""),
+ MGM_ARG("nodeid", Int, Mandatory, "Node ID"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args);
+ CHECK_REPLY(prop, 0);
+
+ if(!prop->get("nodeid",&nodeid)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ delete prop;
+ DBUG_RETURN(nodeid);
+}
+
+extern "C"
+int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
+{
+ DBUG_ENTER("ndb_mgm_report_event");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+ args.put("length", length);
+ BaseString data_string;
+
+ for (int i = 0; i < length; i++)
+ data_string.appfmt(" %u", data[i]);
+
+ args.put("data", data_string.c_str());
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("report event reply", NULL, ""),
+ MGM_ARG("result", String, Mandatory, "Result"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "report event", &args);
+ CHECK_REPLY(prop, -1);
+
+ DBUG_RETURN(0);
+}
+
+extern "C"
+int ndb_mgm_end_session(NdbMgmHandle handle)
+{
+ DBUG_ENTER("ndb_mgm_end_session");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ SocketOutputStream s_output(handle->socket);
+ s_output.println("end session");
+ s_output.println("");
+
+ SocketInputStream in(handle->socket, handle->read_timeout);
+ char buf[32];
+
+ in.gets(buf, sizeof(buf));
+
+ DBUG_RETURN(0);
+}
+
+extern "C"
+int ndb_mgm_get_version(NdbMgmHandle handle,
+ int *major, int *minor, int *build, int len, char* str)
+{
+ DBUG_ENTER("ndb_mgm_get_version");
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("version", NULL, ""),
+ MGM_ARG("id", Int, Mandatory, "ID"),
+ MGM_ARG("major", Int, Mandatory, "Major"),
+ MGM_ARG("minor", Int, Mandatory, "Minor"),
+ MGM_ARG("string", String, Mandatory, "String"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop = ndb_mgm_call(handle, reply, "get version", &args);
+ CHECK_REPLY(prop, 0);
+
+ Uint32 id;
+ if(!prop->get("id",&id)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+ *build= getBuild(id);
+
+ if(!prop->get("major",(Uint32*)major)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ if(!prop->get("minor",(Uint32*)minor)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ BaseString result;
+ if(!prop->get("string", result)){
+ fprintf(handle->errstream, "Unable to get value\n");
+ return 0;
+ }
+
+ strncpy(str, result.c_str(), len);
+
+ delete prop;
+ DBUG_RETURN(1);
+}
+
template class Vector<const ParserRow<ParserDummy>*>;
diff --git a/ndb/src/mgmapi/mgmapi_configuration.hpp b/ndb/src/mgmapi/mgmapi_configuration.hpp
index 9e94b3311bf..7d60a4842a1 100644
--- a/ndb/src/mgmapi/mgmapi_configuration.hpp
+++ b/ndb/src/mgmapi/mgmapi_configuration.hpp
@@ -1,3 +1,19 @@
+/* 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 MGMAPI_CONFIGURATION_HPP
#define MGMAPI_CONFIGURATION_HPP
diff --git a/ndb/src/mgmapi/mgmapi_internal.h b/ndb/src/mgmapi/mgmapi_internal.h
new file mode 100644
index 00000000000..90f93129f2a
--- /dev/null
+++ b/ndb/src/mgmapi/mgmapi_internal.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2005 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 MGMAPI_INTERNAL_H
+#define MGMAPI_INTERNAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <NdbTCP.h>
+
+ /**
+ * Set an integer parameter for a connection
+ *
+ * @param handle the NDB management handle.
+ * @param node1 the node1 id
+ * @param node2 the node2 id
+ * @param param the parameter (e.g. CFG_CONNECTION_SERVER_PORT)
+ * @param value what to set it to
+ * @param reply from ndb_mgmd
+ */
+ int ndb_mgm_set_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int value,
+ struct ndb_mgm_reply* reply);
+
+ /**
+ * Get an integer parameter for a connection
+ *
+ * @param handle the NDB management handle.
+ * @param node1 the node1 id
+ * @param node2 the node2 id
+ * @param param the parameter (e.g. CFG_CONNECTION_SERVER_PORT)
+ * @param value where to store the retreived value. In the case of
+ * error, value is not changed.
+ * @param reply from ndb_mgmd
+ * @return 0 on success. < 0 on error.
+ */
+ int ndb_mgm_get_connection_int_parameter(NdbMgmHandle handle,
+ int node1,
+ int node2,
+ int param,
+ int *value,
+ struct ndb_mgm_reply* reply);
+
+ /**
+ * Convert connection to transporter
+ * @param handle NDB management handle.
+ *
+ * @return socket
+ *
+ * @note the socket is now able to be used as a transporter connection
+ */
+ NDB_SOCKET_TYPE ndb_mgm_convert_to_transporter(NdbMgmHandle *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/ndb/src/mgmapi/ndb_logevent.cpp b/ndb/src/mgmapi/ndb_logevent.cpp
new file mode 100644
index 00000000000..a90d5658506
--- /dev/null
+++ b/ndb/src/mgmapi/ndb_logevent.cpp
@@ -0,0 +1,512 @@
+/* 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 <my_sys.h>
+#include <mgmapi.h>
+
+#include <NdbOut.hpp>
+#include <Properties.hpp>
+#include <socket_io.h>
+#include <InputStream.hpp>
+
+#include <debugger/EventLogger.hpp>
+
+#include "ndb_logevent.hpp"
+
+extern
+int ndb_mgm_listen_event_internal(NdbMgmHandle, const int filter[], int);
+
+struct ndb_logevent_error_msg {
+ enum ndb_logevent_handle_error code;
+ const char *msg;
+};
+
+struct ndb_logevent_error_msg ndb_logevent_error_messages[]= {
+ { NDB_LEH_READ_ERROR, "Read error" },
+ { NDB_LEH_MISSING_EVENT_SPECIFIER, "Missing event specifier" },
+ { NDB_LEH_UNKNOWN_EVENT_VARIABLE, "Unknown event variable" },
+ { NDB_LEH_UNKNOWN_EVENT_TYPE, "Unknown event type" },
+ { NDB_LEH_INTERNAL_ERROR, "Unknown internal error" },
+ { NDB_LEH_NO_ERROR,0}
+};
+
+struct ndb_logevent_handle {
+ NDB_SOCKET_TYPE socket;
+ enum ndb_logevent_handle_error m_error;
+};
+
+extern "C"
+NdbLogEventHandle
+ndb_mgm_create_logevent_handle(NdbMgmHandle mh,
+ const int filter[])
+{
+ int fd= ndb_mgm_listen_event_internal(mh, filter, 1);
+
+ if (fd == -1)
+ return 0;
+
+ NdbLogEventHandle h=
+ (NdbLogEventHandle)my_malloc(sizeof(ndb_logevent_handle),MYF(MY_WME));
+
+ h->socket= fd;
+
+ return h;
+}
+
+extern "C"
+void ndb_mgm_destroy_logevent_handle(NdbLogEventHandle * h)
+{
+ if( !h )
+ return;
+
+ if ( *h )
+ close((*h)->socket);
+
+ my_free((char*)* h,MYF(MY_ALLOW_ZERO_PTR));
+ * h = 0;
+}
+
+#define ROW(a,b,c,d) \
+{ NDB_LE_ ## a, b, c, 0, offsetof(struct ndb_logevent, a.d), \
+ sizeof(((struct ndb_logevent *)0)->a.d) }
+
+#define ROW_FN(a,b,c,d,e) \
+{ NDB_LE_ ## a, b, c, e, offsetof(struct ndb_logevent, a.d), \
+ sizeof(((struct ndb_logevent *)0)->a.d) }
+
+static int ref_to_node(int ref){
+ return ref & 0xFFFF;
+}
+
+struct Ndb_logevent_body_row ndb_logevent_body[]= {
+
+ // Connection
+ ROW( Connected, "node", 1, node),
+
+ ROW( Disconnected, "node", 1, node),
+
+ ROW( CommunicationClosed, "node", 1, node),
+
+ ROW( CommunicationOpened, "node", 1, node),
+
+ ROW( ConnectedApiVersion, "node", 1, node),
+ ROW( ConnectedApiVersion, "version", 2, version),
+
+ /* CHECKPOINT */
+
+ ROW( GlobalCheckpointStarted, "gci", 1, gci),
+
+ ROW( GlobalCheckpointCompleted, "gci", 1, gci),
+
+ ROW( LocalCheckpointStarted, "lci", 1, lci),
+ ROW( LocalCheckpointStarted, "keep_gci", 2, keep_gci),
+ ROW( LocalCheckpointStarted, "restore_gci", 3, restore_gci),
+
+ ROW( LocalCheckpointCompleted, "lci", 1, lci),
+
+ ROW( LCPStoppedInCalcKeepGci, "data", 1, data),
+
+ ROW( LCPFragmentCompleted, "node", 1, node),
+ ROW( LCPFragmentCompleted, "table_id", 2, table_id),
+ ROW( LCPFragmentCompleted, "fragment_id", 3, fragment_id),
+
+ ROW( UndoLogBlocked, "acc_count", 1, acc_count),
+ ROW( UndoLogBlocked, "tup_count", 2, tup_count),
+
+ /* STARTUP */
+ ROW( NDBStartStarted, "version", 1, version),
+
+ ROW( NDBStartCompleted, "version", 1, version),
+
+// ROW( STTORRYRecieved),
+
+ ROW( StartPhaseCompleted, "phase", 1, phase),
+ ROW( StartPhaseCompleted, "starttype", 2, starttype),
+
+ ROW( CM_REGCONF, "own_id", 1, own_id),
+ ROW( CM_REGCONF, "president_id", 2, president_id),
+ ROW( CM_REGCONF, "dynamic_id", 3, dynamic_id),
+
+ ROW( CM_REGREF, "own_id", 1, own_id),
+ ROW( CM_REGREF, "other_id", 2, other_id),
+ ROW( CM_REGREF, "cause", 3, cause),
+
+ ROW( FIND_NEIGHBOURS, "own_id", 1, own_id),
+ ROW( FIND_NEIGHBOURS, "left_id", 3, left_id),
+ ROW( FIND_NEIGHBOURS, "right_id", 3, right_id),
+ ROW( FIND_NEIGHBOURS, "dynamic_id", 4, dynamic_id),
+
+ ROW( NDBStopStarted, "stoptype", 1, stoptype),
+
+ ROW( NDBStopCompleted, "action", 1, action),
+ ROW( NDBStopCompleted, "signum", 2, signum),
+
+ ROW( NDBStopForced, "action", 1, action),
+ ROW( NDBStopForced, "signum", 2, signum),
+ ROW( NDBStopForced, "error", 3, error),
+ ROW( NDBStopForced, "sphase", 4, sphase),
+ ROW( NDBStopForced, "extra", 5, extra),
+
+// ROW( NDBStopAborted),
+
+ ROW( StartREDOLog, "node", 1, node),
+ ROW( StartREDOLog, "keep_gci", 2, keep_gci),
+ ROW( StartREDOLog, "completed_gci", 3, completed_gci),
+ ROW( StartREDOLog, "restorable_gci", 4, restorable_gci),
+
+ ROW( StartLog, "log_part", 1, log_part),
+ ROW( StartLog, "start_mb", 2, start_mb),
+ ROW( StartLog, "stop_mb", 3, stop_mb),
+ ROW( StartLog, "gci", 4, gci),
+
+ ROW( UNDORecordsExecuted, "block", 1, block),
+ ROW( UNDORecordsExecuted, "data1", 2, data1),
+ ROW( UNDORecordsExecuted, "data2", 3, data2),
+ ROW( UNDORecordsExecuted, "data3", 4, data3),
+ ROW( UNDORecordsExecuted, "data4", 5, data4),
+ ROW( UNDORecordsExecuted, "data5", 6, data5),
+ ROW( UNDORecordsExecuted, "data6", 7, data6),
+ ROW( UNDORecordsExecuted, "data7", 8, data7),
+ ROW( UNDORecordsExecuted, "data8", 9, data8),
+ ROW( UNDORecordsExecuted, "data9", 10, data9),
+ ROW( UNDORecordsExecuted, "data10", 11, data10),
+
+ /* NODERESTART */
+// ROW( NR_CopyDict),
+
+// ROW( NR_CopyDistr),
+
+ ROW( NR_CopyFragsStarted, "dest_node", 1, dest_node),
+
+ ROW( NR_CopyFragDone, "dest_node", 1, dest_node),
+ ROW( NR_CopyFragDone, "table_id", 2, table_id),
+ ROW( NR_CopyFragDone, "fragment_id", 3, fragment_id),
+
+ ROW( NR_CopyFragsCompleted, "dest_node", 1, dest_node),
+
+ ROW( NodeFailCompleted, "block", 1, block), /* 0 = all */
+ ROW( NodeFailCompleted, "failed_node", 2, failed_node),
+ ROW( NodeFailCompleted, "completing_node", 3, completing_node), /* 0 = all */
+
+ ROW( NODE_FAILREP, "failed_node", 1, failed_node),
+ ROW( NODE_FAILREP, "failure_state", 2, failure_state),
+
+ /* TODO */
+ ROW( ArbitState, "code", 1, code),
+ ROW( ArbitState, "arbit_node", 2, arbit_node),
+ ROW( ArbitState, "ticket_0", 3, ticket_0),
+ ROW( ArbitState, "ticket_1", 4, ticket_1),
+
+ /* TODO */
+ ROW( ArbitResult, "code", 1, code),
+ ROW( ArbitResult, "arbit_node", 2, arbit_node),
+ ROW( ArbitResult, "ticket_0", 3, ticket_0),
+ ROW( ArbitResult, "ticket_1", 4, ticket_1),
+
+// ROW( GCP_TakeoverStarted),
+
+// ROW( GCP_TakeoverCompleted),
+
+// ROW( LCP_TakeoverStarted),
+
+ ROW( LCP_TakeoverCompleted, "state", 1, state),
+
+ /* STATISTIC */
+ ROW( TransReportCounters, "trans_count", 1, trans_count),
+ ROW( TransReportCounters, "commit_count", 2, commit_count),
+ ROW( TransReportCounters, "read_count", 3, read_count),
+ ROW( TransReportCounters, "simple_read_count", 4, simple_read_count),
+ ROW( TransReportCounters, "write_count", 5, write_count),
+ ROW( TransReportCounters, "attrinfo_count", 6, attrinfo_count),
+ ROW( TransReportCounters, "conc_op_count", 7, conc_op_count),
+ ROW( TransReportCounters, "abort_count", 8, abort_count),
+ ROW( TransReportCounters, "scan_count", 9, scan_count),
+ ROW( TransReportCounters, "range_scan_count", 10, range_scan_count),
+
+ ROW( OperationReportCounters, "ops", 1, ops),
+
+ ROW( TableCreated, "table_id", 1, table_id),
+
+ ROW( JobStatistic, "mean_loop_count", 1, mean_loop_count),
+
+ ROW( SendBytesStatistic, "to_node", 1, to_node),
+ ROW( SendBytesStatistic, "mean_sent_bytes", 2, mean_sent_bytes),
+
+ ROW( ReceiveBytesStatistic, "from_node", 1, from_node),
+ ROW( ReceiveBytesStatistic, "mean_received_bytes", 2, mean_received_bytes),
+
+ ROW( MemoryUsage, "gth", 1, gth),
+ ROW( MemoryUsage, "page_size_kb", 2, page_size_kb),
+ ROW( MemoryUsage, "pages_used", 3, pages_used),
+ ROW( MemoryUsage, "pages_total", 4, pages_total),
+ ROW( MemoryUsage, "block", 5, block),
+
+ /* ERROR */
+ ROW( TransporterError, "to_node", 1, to_node),
+ ROW( TransporterError, "code", 2, code),
+
+ ROW( TransporterWarning, "to_node", 1, to_node),
+ ROW( TransporterWarning, "code", 2, code),
+
+ ROW( MissedHeartbeat, "node", 1, node),
+ ROW( MissedHeartbeat, "count", 2, count),
+
+ ROW( DeadDueToHeartbeat, "node", 1, node),
+
+ /* TODO */
+// ROW( WarningEvent),
+
+ /* INFO */
+ ROW( SentHeartbeat, "node", 1, node),
+
+ ROW( CreateLogBytes, "node", 1, node),
+
+ /* TODO */
+// ROW( InfoEvent),
+
+ // Backup
+ ROW_FN( BackupStarted, "starting_node", 1, starting_node, ref_to_node),
+ ROW( BackupStarted, "backup_id", 2, backup_id),
+
+ ROW_FN(BackupFailedToStart,"starting_node",1, starting_node, ref_to_node),
+ ROW( BackupFailedToStart, "error", 2, error),
+
+ ROW_FN( BackupCompleted, "starting_node", 1, starting_node, ref_to_node),
+ ROW( BackupCompleted, "backup_id", 2, backup_id),
+ ROW( BackupCompleted, "start_gci", 3, start_gci),
+ ROW( BackupCompleted, "stop_gci", 4, stop_gci),
+ ROW( BackupCompleted, "n_bytes", 5, n_bytes),
+ ROW( BackupCompleted, "n_records", 6, n_records),
+ ROW( BackupCompleted, "n_log_bytes", 7, n_log_bytes),
+ ROW( BackupCompleted, "n_log_records", 8, n_log_records),
+
+ ROW_FN( BackupAborted, "starting_node", 1, starting_node, ref_to_node),
+ ROW( BackupAborted, "backup_id", 2, backup_id),
+ ROW( BackupAborted, "error", 3, error),
+
+ ROW( SingleUser, "type", 1, type),
+ ROW( SingleUser, "node_id", 2, node_id),
+ { NDB_LE_ILLEGAL_TYPE, 0, 0, 0, 0, 0}
+};
+
+struct Ndb_logevent_header_row {
+ const char *token; // token to use for text transfer
+ int offset; // offset into struct ndb_logevent
+ int size;
+};
+
+#define ROW2(a,b) \
+{ a, offsetof(struct ndb_logevent, b), \
+ sizeof(((struct ndb_logevent *)0)->b) }
+
+struct Ndb_logevent_header_row ndb_logevent_header[]= {
+ ROW2( "type", type),
+ ROW2( "time", time),
+ ROW2( "source_nodeid", source_nodeid),
+ { 0, 0, 0 }
+};
+
+static int
+insert_row(const char * pair, Properties & p){
+ BaseString tmp(pair);
+
+ tmp.trim(" \t\n\r");
+ Vector<BaseString> split;
+ tmp.split(split, ":=", 2);
+ if(split.size() != 2)
+ return -1;
+ p.put(split[0].trim().c_str(), split[1].trim().c_str());
+
+ return 0;
+}
+
+static
+int memcpy_atoi(void *dst, const char *str, int sz)
+{
+ switch (sz)
+ {
+ case 1:
+ {
+ Int8 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ case 2:
+ {
+ Int16 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ case 4:
+ {
+ Int32 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ case 8:
+ {
+ Int64 val= atoi(str);
+ memcpy(dst,&val,sz);
+ return 0;
+ }
+ default:
+ {
+ return -1;
+ }
+ }
+}
+
+extern "C"
+int ndb_logevent_get_next(const NdbLogEventHandle h,
+ struct ndb_logevent *dst,
+ unsigned timeout_in_milliseconds)
+{
+ SocketInputStream in(h->socket, timeout_in_milliseconds);
+
+ Properties p;
+ char buf[256];
+
+ struct timeval start_time;
+ gettimeofday(&start_time, 0);
+
+ /* header */
+ while (1) {
+ if (in.gets(buf,sizeof(buf)) == 0)
+ {
+ h->m_error= NDB_LEH_READ_ERROR;
+ return -1;
+ }
+ if ( buf[0] == 0 )
+ {
+ // timed out
+ return 0;
+ }
+ if ( strcmp("log event reply\n", buf) == 0 )
+ break;
+
+ if ( strcmp("<PING>\n", buf) )
+ ndbout_c("skipped: %s", buf);
+
+ struct timeval now;
+ gettimeofday(&now, 0);
+ unsigned elapsed_ms= (now.tv_sec-start_time.tv_sec)*1000 +
+ ((signed int)now.tv_usec-(signed int)start_time.tv_usec)/1000;
+
+ if (elapsed_ms >= timeout_in_milliseconds)
+ {
+ // timed out
+ return 0;
+ }
+
+ new (&in) SocketInputStream(h->socket, timeout_in_milliseconds-elapsed_ms);
+ }
+
+ /* read name-value pairs into properties object */
+ while (1)
+ {
+ if (in.gets(buf,sizeof(buf)) == 0)
+ {
+ h->m_error= NDB_LEH_READ_ERROR;
+ return -1;
+ }
+ if ( buf[0] == 0 )
+ {
+ // timed out
+ return 0;
+ }
+ if ( buf[0] == '\n' )
+ {
+ break;
+ }
+ if (insert_row(buf,p))
+ {
+ h->m_error= NDB_LEH_READ_ERROR;
+ return -1;
+ }
+ }
+
+ int i;
+ const char *val;
+
+ dst->type= (enum Ndb_logevent_type)-1;
+ /* fill in header info from p*/
+ for (i= 0; ndb_logevent_header[i].token; i++)
+ {
+ if ( p.get(ndb_logevent_header[i].token, &val) == 0 )
+ {
+ ndbout_c("missing: %s\n", ndb_logevent_header[i].token);
+ h->m_error= NDB_LEH_MISSING_EVENT_SPECIFIER;
+ return -1;
+ }
+ if ( memcpy_atoi((char *)dst+ndb_logevent_header[i].offset, val,
+ ndb_logevent_header[i].size) )
+ {
+ h->m_error= NDB_LEH_INTERNAL_ERROR;
+ return -1;
+ }
+ }
+
+ Uint32 level;
+ LogLevel::EventCategory category;
+ Logger::LoggerLevel severity;
+ EventLoggerBase::EventTextFunction text_fn;
+
+ /* fill in rest of header info event_lookup */
+ if (EventLoggerBase::event_lookup(dst->type,category,level,severity,text_fn))
+ {
+ ndbout_c("unknown type: %d\n", dst->type);
+ h->m_error= NDB_LEH_UNKNOWN_EVENT_TYPE;
+ return -1;
+ }
+ dst->category= (enum ndb_mgm_event_category)category;
+ dst->severity= (enum ndb_mgm_event_severity)severity;
+ dst->level= level;
+
+ /* fill in header info from p */
+ for (i= 0; ndb_logevent_body[i].token; i++)
+ {
+ if ( ndb_logevent_body[i].type != dst->type )
+ continue;
+ if ( p.get(ndb_logevent_body[i].token, &val) == 0 )
+ {
+ h->m_error= NDB_LEH_UNKNOWN_EVENT_VARIABLE;
+ return -1;
+ }
+ if ( memcpy_atoi((char *)dst+ndb_logevent_body[i].offset, val,
+ ndb_logevent_body[i].size) )
+ {
+ h->m_error= NDB_LEH_INTERNAL_ERROR;
+ return -1;
+ }
+ }
+ return 1;
+}
+
+extern "C"
+int ndb_logevent_get_latest_error(const NdbLogEventHandle h)
+{
+ return h->m_error;
+}
+
+extern "C"
+const char *ndb_logevent_get_latest_error_msg(const NdbLogEventHandle h)
+{
+ for (int i= 0; ndb_logevent_error_messages[i].msg; i++)
+ if (ndb_logevent_error_messages[i].code == h->m_error)
+ return ndb_logevent_error_messages[i].msg;
+ return "<unknown error msg>";
+}
diff --git a/ndb/src/mgmapi/ndb_logevent.hpp b/ndb/src/mgmapi/ndb_logevent.hpp
new file mode 100644
index 00000000000..cb1a0e388e5
--- /dev/null
+++ b/ndb/src/mgmapi/ndb_logevent.hpp
@@ -0,0 +1,34 @@
+/* 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 NDB_LOGEVENT_HPP
+#define NDB_LOGEVENT_HPP
+
+#include <ndb_logevent.h>
+
+struct Ndb_logevent_body_row {
+ enum Ndb_logevent_type type; // type
+ const char *token; // token to use for text transfer
+ int index; // index into theData array
+ int (*index_fn)(int); // conversion function on the data array[index]
+ int offset; // offset into struct ndb_logevent
+ int size; // offset into struct ndb_logevent
+};
+
+extern
+struct Ndb_logevent_body_row ndb_logevent_body[];
+
+#endif
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index 72debcc26a9..58b98671b14 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -25,6 +25,7 @@
#endif
#include <mgmapi.h>
+#include <util/BaseString.hpp>
class MgmtSrvr;
@@ -70,6 +71,9 @@ private:
*/
void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
+ void executeCommand(Vector<BaseString> &command_list,
+ unsigned command_pos,
+ int *node_ids, int no_of_nodes);
/**
* Parse the block specification part of the LOG* commands,
* things after LOG*: [BLOCK = {ALL|<blockName>+}]
@@ -104,10 +108,14 @@ private:
public:
void executeStop(int processId, const char* parameters, bool all);
+ void executeStop(Vector<BaseString> &command_list, unsigned command_pos,
+ int *node_ids, int no_of_nodes);
void executeEnterSingleUser(char* parameters);
void executeExitSingleUser(char* parameters);
void executeStart(int processId, const char* parameters, bool all);
void executeRestart(int processId, const char* parameters, bool all);
+ void executeRestart(Vector<BaseString> &command_list, unsigned command_pos,
+ int *node_ids, int no_of_nodes);
void executeLogLevel(int processId, const char* parameters, bool all);
void executeError(int processId, const char* parameters, bool all);
void executeLog(int processId, const char* parameters, bool all);
@@ -154,6 +162,7 @@ private:
NdbMgmHandle m_mgmsrv;
NdbMgmHandle m_mgmsrv2;
+ const char *m_constr;
bool m_connected;
int m_verbose;
int try_reconnect;
@@ -382,22 +391,7 @@ convert(const char* s, int& val) {
CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
: m_verbose(verbose)
{
- m_mgmsrv = ndb_mgm_create_handle();
- if(m_mgmsrv == NULL) {
- ndbout_c("Cannot create handle to management server.");
- exit(-1);
- }
- m_mgmsrv2 = ndb_mgm_create_handle();
- if(m_mgmsrv2 == NULL) {
- ndbout_c("Cannot create handle to management server.");
- exit(-1);
- }
- if (ndb_mgm_set_connectstring(m_mgmsrv, _host))
- {
- printError();
- exit(-1);
- }
-
+ m_constr= _host;
m_connected= false;
m_event_thread= 0;
try_reconnect = 0;
@@ -414,8 +408,6 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
CommandInterpreter::~CommandInterpreter()
{
disconnect();
- ndb_mgm_destroy_handle(&m_mgmsrv);
- ndb_mgm_destroy_handle(&m_mgmsrv2);
}
static bool
@@ -437,15 +429,14 @@ emptyString(const char* s)
void
CommandInterpreter::printError()
{
- if (ndb_mgm_check_connection(m_mgmsrv))
- {
- m_connected= false;
- disconnect();
- }
ndbout_c("* %5d: %s",
ndb_mgm_get_latest_error(m_mgmsrv),
ndb_mgm_get_latest_error_msg(m_mgmsrv));
ndbout_c("* %s", ndb_mgm_get_latest_error_desc(m_mgmsrv));
+ if (ndb_mgm_check_connection(m_mgmsrv))
+ {
+ disconnect();
+ }
}
//*****************************************************************************
@@ -459,7 +450,9 @@ event_thread_run(void* m)
NdbMgmHandle handle= *(NdbMgmHandle*)m;
- int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 };
+ int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP,
+ 1, NDB_MGM_EVENT_CATEGORY_STARTUP,
+ 0 };
int fd = ndb_mgm_listen_event(handle, filter);
if (fd != NDB_INVALID_SOCKET)
{
@@ -487,68 +480,97 @@ event_thread_run(void* m)
}
bool
-CommandInterpreter::connect()
+CommandInterpreter::connect()
{
DBUG_ENTER("CommandInterpreter::connect");
- if(!m_connected)
+
+ if(m_connected)
+ DBUG_RETURN(m_connected);
+
+ m_mgmsrv = ndb_mgm_create_handle();
+ if(m_mgmsrv == NULL) {
+ ndbout_c("Cannot create handle to management server.");
+ exit(-1);
+ }
+ m_mgmsrv2 = ndb_mgm_create_handle();
+ if(m_mgmsrv2 == NULL) {
+ ndbout_c("Cannot create 2:nd handle to management server.");
+ exit(-1);
+ }
+
+ if (ndb_mgm_set_connectstring(m_mgmsrv, m_constr))
{
- if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
+ printError();
+ exit(-1);
+ }
+
+ if(ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
+ DBUG_RETURN(m_connected); // couldn't connect, always false
+
+ const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
+ unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
+ BaseString constr;
+ constr.assfmt("%s:%d",host,port);
+ if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) &&
+ !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
+ {
+ DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
+ host, port));
+ assert(m_event_thread == 0);
+ assert(do_event_thread == 0);
+ do_event_thread= 0;
+ m_event_thread = NdbThread_Create(event_thread_run,
+ (void**)&m_mgmsrv2,
+ 32768,
+ "CommandInterpreted_event_thread",
+ NDB_THREAD_PRIO_LOW);
+ if (m_event_thread != 0)
{
- const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
- unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
- if(!ndb_mgm_set_connectstring(m_mgmsrv2,
- BaseString(host).appfmt(":%d",port).c_str())
- &&
- !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
- {
- assert(m_event_thread == 0);
- assert(do_event_thread == 0);
- do_event_thread= 0;
- m_event_thread = NdbThread_Create(event_thread_run,
- (void**)&m_mgmsrv2,
- 32768,
- "CommandInterpreted_event_thread",
- NDB_THREAD_PRIO_LOW);
- if (m_event_thread != 0)
- {
- int iter= 1000; // try for 30 seconds
- while(do_event_thread == 0 &&
- iter-- > 0)
- NdbSleep_MilliSleep(30);
- }
- if (m_event_thread == 0 ||
- do_event_thread == 0 ||
- do_event_thread == -1)
- {
- DBUG_PRINT("info",("Warning, event thread startup failed, "
- "degraded printouts as result, errno=%d",
- errno));
- printf("Warning, event thread startup failed, "
- "degraded printouts as result, errno=%d\n", errno);
- do_event_thread= 0;
- if (m_event_thread)
- {
- void *res;
- NdbThread_WaitFor(m_event_thread, &res);
- NdbThread_Destroy(&m_event_thread);
- }
- ndb_mgm_disconnect(m_mgmsrv2);
- }
- }
- else
- {
- printf("Warning, event connect failed, degraded printouts as result\n");
- }
- m_connected= true;
- DBUG_PRINT("info",("Connected to Management Server at: %s:%d",
- host,port));
- if (m_verbose)
+ DBUG_PRINT("info",("Thread created ok, waiting for started..."));
+ int iter= 1000; // try for 30 seconds
+ while(do_event_thread == 0 &&
+ iter-- > 0)
+ NdbSleep_MilliSleep(30);
+ }
+ if (m_event_thread == 0 ||
+ do_event_thread == 0 ||
+ do_event_thread == -1)
+ {
+ DBUG_PRINT("info",("Warning, event thread startup failed, "
+ "degraded printouts as result, errno=%d",
+ errno));
+ printf("Warning, event thread startup failed, "
+ "degraded printouts as result, errno=%d\n", errno);
+ do_event_thread= 0;
+ if (m_event_thread)
{
- printf("Connected to Management Server at: %s:%d\n",
- host, port);
+ void *res;
+ NdbThread_WaitFor(m_event_thread, &res);
+ NdbThread_Destroy(&m_event_thread);
}
+ ndb_mgm_disconnect(m_mgmsrv2);
}
}
+ else
+ {
+ DBUG_PRINT("warning",
+ ("Could not do 2:nd connect to mgmtserver for event listening"));
+ DBUG_PRINT("info", ("code: %d, msg: %s",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2)));
+ printf("Warning, event connect failed, degraded printouts as result\n");
+ printf("code: %d, msg: %s\n",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2));
+ }
+ m_connected= true;
+ DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port));
+ if (m_verbose)
+ {
+ printf("Connected to Management Server at: %s:%d\n",
+ host, port);
+ }
+
DBUG_RETURN(m_connected);
}
@@ -556,20 +578,18 @@ bool
CommandInterpreter::disconnect()
{
DBUG_ENTER("CommandInterpreter::disconnect");
+
if (m_event_thread) {
void *res;
do_event_thread= 0;
NdbThread_WaitFor(m_event_thread, &res);
NdbThread_Destroy(&m_event_thread);
m_event_thread= 0;
- ndb_mgm_disconnect(m_mgmsrv2);
+ ndb_mgm_destroy_handle(&m_mgmsrv2);
}
if (m_connected)
{
- if (ndb_mgm_disconnect(m_mgmsrv) == -1) {
- ndbout_c("Could not disconnect from management server");
- printError();
- }
+ ndb_mgm_destroy_handle(&m_mgmsrv);
m_connected= false;
}
DBUG_RETURN(true);
@@ -631,9 +651,16 @@ CommandInterpreter::execute_impl(const char *_line)
}
} while (do_continue);
// if there is anything in the line proceed
+ Vector<BaseString> command_list;
+ {
+ BaseString tmp(line);
+ tmp.split(command_list);
+ for (unsigned i= 0; i < command_list.size();)
+ command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0);
+ }
char* firstToken = strtok(line, " ");
char* allAfterFirstToken = strtok(NULL, "");
-
+
if (strcasecmp(firstToken, "HELP") == 0 ||
strcasecmp(firstToken, "?") == 0) {
executeHelp(allAfterFirstToken);
@@ -711,22 +738,45 @@ CommandInterpreter::execute_impl(const char *_line)
analyseAfterFirstToken(-1, allAfterFirstToken);
} else {
/**
- * First token should be a digit, node ID
+ * First tokens should be digits, node ID's
*/
- int nodeId;
-
- if (! convert(firstToken, nodeId)) {
+ int node_ids[MAX_NODES];
+ unsigned pos;
+ for (pos= 0; pos < command_list.size(); pos++)
+ {
+ int node_id;
+ if (convert(command_list[pos].c_str(), node_id))
+ {
+ if (node_id <= 0) {
+ ndbout << "Invalid node ID: " << command_list[pos].c_str()
+ << "." << endl;
+ DBUG_RETURN(true);
+ }
+ node_ids[pos]= node_id;
+ continue;
+ }
+ break;
+ }
+ int no_of_nodes= pos;
+ if (no_of_nodes == 0)
+ {
+ /* No digit found */
invalid_command(_line);
DBUG_RETURN(true);
}
-
- if (nodeId <= 0) {
- ndbout << "Invalid node ID: " << firstToken << "." << endl;
+ if (pos == command_list.size())
+ {
+ /* No command found */
+ invalid_command(_line);
DBUG_RETURN(true);
}
-
- analyseAfterFirstToken(nodeId, allAfterFirstToken);
-
+ if (no_of_nodes == 1)
+ {
+ analyseAfterFirstToken(node_ids[0], allAfterFirstToken);
+ DBUG_RETURN(true);
+ }
+ executeCommand(command_list, pos, node_ids, no_of_nodes);
+ DBUG_RETURN(true);
}
DBUG_RETURN(true);
}
@@ -796,6 +846,27 @@ CommandInterpreter::analyseAfterFirstToken(int processId,
ndbout << endl;
}
+void
+CommandInterpreter::executeCommand(Vector<BaseString> &command_list,
+ unsigned command_pos,
+ int *node_ids, int no_of_nodes)
+{
+ const char *cmd= command_list[command_pos].c_str();
+ if (strcasecmp("STOP", cmd) == 0)
+ {
+ executeStop(command_list, command_pos+1, node_ids, no_of_nodes);
+ return;
+ }
+ if (strcasecmp("RESTART", cmd) == 0)
+ {
+ executeRestart(command_list, command_pos+1, node_ids, no_of_nodes);
+ return;
+ }
+ ndbout_c("Invalid command: '%s' after multi node id list. "
+ "Expected STOP or RESTART.", cmd);
+ return;
+}
+
/**
* Get next nodeid larger than the give node_id. node_id will be
* set to the next node_id in the list. node_id should be set
@@ -986,42 +1057,21 @@ CommandInterpreter::executeShutdown(char* parameters)
NdbAutoPtr<char> ap1((char*)state);
int result = 0;
- result = ndb_mgm_stop(m_mgmsrv, 0, 0);
+ int need_disconnect;
+ result = ndb_mgm_stop3(m_mgmsrv, -1, 0, 0, &need_disconnect);
if (result < 0) {
- ndbout << "Shutdown off NDB Cluster storage node(s) failed." << endl;
+ ndbout << "Shutdown of NDB Cluster node(s) failed." << endl;
printError();
return result;
}
- ndbout << result << " NDB Cluster storage node(s) have shutdown." << endl;
-
- int mgm_id= 0;
- for(int i=0; i < state->no_of_nodes; i++) {
- if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM &&
- state->node_states[i].version != 0){
- if (mgm_id == 0)
- mgm_id= state->node_states[i].node_id;
- else {
- ndbout << "Unable to locate management server, "
- << "shutdown manually with <id> STOP"
- << endl;
- return 1;
- }
- }
- }
+ ndbout << result << " NDB Cluster node(s) have shutdown." << endl;
- result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id);
- if (result <= 0) {
- ndbout << "Shutdown of NDB Cluster management server failed." << endl;
- printError();
- if (result == 0)
- return 1;
- return result;
+ if(need_disconnect) {
+ ndbout << "Disconnecting to allow management server to shutdown."
+ << endl;
+ disconnect();
}
-
- m_connected= false;
- disconnect();
- ndbout << "NDB Cluster management server shutdown." << endl;
return 0;
}
@@ -1085,7 +1135,7 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
}
if (node_state->node_group >= 0) {
ndbout << ", Nodegroup: " << node_state->node_group;
- if (node_state->dynamic_id == master_id)
+ if (master_id && node_state->dynamic_id == master_id)
ndbout << ", Master";
}
}
@@ -1245,12 +1295,7 @@ CommandInterpreter::executeConnect(char* parameters)
{
disconnect();
if (!emptyString(parameters)) {
- if (ndb_mgm_set_connectstring(m_mgmsrv,
- BaseString(parameters).trim().c_str()))
- {
- printError();
- return;
- }
+ m_constr= BaseString(parameters).trim().c_str();
}
connect();
}
@@ -1268,7 +1313,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
DBUG_VOID_RETURN;
}
- enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL;
+ enum ndb_mgm_event_severity severity = NDB_MGM_EVENT_SEVERITY_ALL;
char * tmpString = my_strdup(parameters,MYF(MY_WME));
My_auto_ptr<char> ap1(tmpString);
@@ -1276,7 +1321,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
char * item = strtok_r(tmpString, " ", &tmpPtr);
int enable;
- Uint32 *enabled = ndb_mgm_get_logfilter(m_mgmsrv);
+ const unsigned int *enabled= ndb_mgm_get_logfilter(m_mgmsrv);
if(enabled == NULL) {
ndbout << "Couldn't get status" << endl;
printError();
@@ -1298,8 +1343,8 @@ CommandInterpreter::executeClusterLog(char* parameters)
printf("enabled[%d] = %d\n", i, enabled[i]);
#endif
ndbout << "Severities enabled: ";
- for(i = 1; i < (int)NDB_MGM_CLUSTERLOG_ALL; i++) {
- const char *str= ndb_mgm_get_clusterlog_level_string((ndb_mgm_clusterlog_level)i);
+ for(i = 1; i < (int)NDB_MGM_EVENT_SEVERITY_ALL; i++) {
+ const char *str= ndb_mgm_get_event_severity_string((ndb_mgm_event_severity)i);
if (str == 0)
{
DBUG_ASSERT(false);
@@ -1333,8 +1378,10 @@ CommandInterpreter::executeClusterLog(char* parameters)
int res_enable;
item = strtok_r(NULL, " ", &tmpPtr);
if (item == NULL) {
- res_enable= ndb_mgm_filter_clusterlog(m_mgmsrv,
- NDB_MGM_CLUSTERLOG_ON, enable, NULL);
+ res_enable=
+ ndb_mgm_set_clusterlog_severity_filter(m_mgmsrv,
+ NDB_MGM_EVENT_SEVERITY_ON,
+ enable, NULL);
if (res_enable < 0)
{
ndbout << "Couldn't set filter" << endl;
@@ -1346,32 +1393,33 @@ CommandInterpreter::executeClusterLog(char* parameters)
}
do {
- severity= NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL;
+ severity= NDB_MGM_ILLEGAL_EVENT_SEVERITY;
if (strcasecmp(item, "ALL") == 0) {
- severity = NDB_MGM_CLUSTERLOG_ALL;
+ severity = NDB_MGM_EVENT_SEVERITY_ALL;
} else if (strcasecmp(item, "ALERT") == 0) {
- severity = NDB_MGM_CLUSTERLOG_ALERT;
+ severity = NDB_MGM_EVENT_SEVERITY_ALERT;
} else if (strcasecmp(item, "CRITICAL") == 0) {
- severity = NDB_MGM_CLUSTERLOG_CRITICAL;
+ severity = NDB_MGM_EVENT_SEVERITY_CRITICAL;
} else if (strcasecmp(item, "ERROR") == 0) {
- severity = NDB_MGM_CLUSTERLOG_ERROR;
+ severity = NDB_MGM_EVENT_SEVERITY_ERROR;
} else if (strcasecmp(item, "WARNING") == 0) {
- severity = NDB_MGM_CLUSTERLOG_WARNING;
+ severity = NDB_MGM_EVENT_SEVERITY_WARNING;
} else if (strcasecmp(item, "INFO") == 0) {
- severity = NDB_MGM_CLUSTERLOG_INFO;
+ severity = NDB_MGM_EVENT_SEVERITY_INFO;
} else if (strcasecmp(item, "DEBUG") == 0) {
- severity = NDB_MGM_CLUSTERLOG_DEBUG;
+ severity = NDB_MGM_EVENT_SEVERITY_DEBUG;
} else if (strcasecmp(item, "OFF") == 0 ||
strcasecmp(item, "ON") == 0) {
if (enable < 0) // only makes sense with toggle
- severity = NDB_MGM_CLUSTERLOG_ON;
+ severity = NDB_MGM_EVENT_SEVERITY_ON;
}
- if (severity == NDB_MGM_ILLEGAL_CLUSTERLOG_LEVEL) {
+ if (severity == NDB_MGM_ILLEGAL_EVENT_SEVERITY) {
ndbout << "Invalid severity level: " << item << endl;
DBUG_VOID_RETURN;
}
- res_enable = ndb_mgm_filter_clusterlog(m_mgmsrv, severity, enable, NULL);
+ res_enable= ndb_mgm_set_clusterlog_severity_filter(m_mgmsrv, severity,
+ enable, NULL);
if (res_enable < 0)
{
ndbout << "Couldn't set filter" << endl;
@@ -1390,24 +1438,69 @@ CommandInterpreter::executeClusterLog(char* parameters)
//*****************************************************************************
void
-CommandInterpreter::executeStop(int processId, const char *, bool all)
+CommandInterpreter::executeStop(int processId, const char *parameters,
+ bool all)
{
- int result = 0;
- if(all) {
- result = ndb_mgm_stop(m_mgmsrv, 0, 0);
- } else {
- result = ndb_mgm_stop(m_mgmsrv, 1, &processId);
+ Vector<BaseString> command_list;
+ if (parameters)
+ {
+ BaseString tmp(parameters);
+ tmp.split(command_list);
+ for (unsigned i= 0; i < command_list.size();)
+ command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0);
}
- if (result < 0) {
- ndbout << "Shutdown failed." << endl;
+ if (all)
+ executeStop(command_list, 0, 0, 0);
+ else
+ executeStop(command_list, 0, &processId, 1);
+}
+
+void
+CommandInterpreter::executeStop(Vector<BaseString> &command_list,
+ unsigned command_pos,
+ int *node_ids, int no_of_nodes)
+{
+ int need_disconnect;
+ int abort= 0;
+ for (; command_pos < command_list.size(); command_pos++)
+ {
+ const char *item= command_list[command_pos].c_str();
+ if (strcasecmp(item, "-A") == 0)
+ {
+ abort= 1;
+ continue;
+ }
+ ndbout_c("Invalid option: %s. Expecting -A after STOP",
+ item);
+ return;
+ }
+
+ int result= ndb_mgm_stop3(m_mgmsrv, no_of_nodes, node_ids, abort,
+ &need_disconnect);
+ if (result < 0)
+ {
+ ndbout_c("Shutdown failed.");
printError();
- } else
+ }
+ else
+ {
+ if (node_ids == 0)
+ ndbout_c("NDB Cluster has shutdown.");
+ else
{
- if(all)
- ndbout << "NDB Cluster has shutdown." << endl;
- else
- ndbout << "Node " << processId << " has shutdown." << endl;
+ ndbout << "Node";
+ for (int i= 0; i < no_of_nodes; i++)
+ ndbout << " " << node_ids[i];
+ ndbout_c(" has shutdown.");
}
+ }
+
+ if(need_disconnect)
+ {
+ ndbout << "Disconnecting to allow Management Server to shutdown" << endl;
+ disconnect();
+ }
+
}
void
@@ -1473,47 +1566,77 @@ CommandInterpreter::executeStart(int processId, const char* parameters,
void
CommandInterpreter::executeRestart(int processId, const char* parameters,
- bool all)
+ bool all)
+{
+ Vector<BaseString> command_list;
+ if (parameters)
+ {
+ BaseString tmp(parameters);
+ tmp.split(command_list);
+ for (unsigned i= 0; i < command_list.size();)
+ command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0);
+ }
+ if (all)
+ executeRestart(command_list, 0, 0, 0);
+ else
+ executeRestart(command_list, 0, &processId, 1);
+}
+
+void
+CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
+ unsigned command_pos,
+ int *node_ids, int no_of_nodes)
{
int result;
- int nostart = 0;
- int initialstart = 0;
- int abort = 0;
-
- if(parameters != 0 && strlen(parameters) != 0){
- char * tmpString = my_strdup(parameters,MYF(MY_WME));
- My_auto_ptr<char> ap1(tmpString);
- char * tmpPtr = 0;
- char * item = strtok_r(tmpString, " ", &tmpPtr);
- while(item != NULL){
- if(strcasecmp(item, "-N") == 0)
- nostart = 1;
- if(strcasecmp(item, "-I") == 0)
- initialstart = 1;
- if(strcasecmp(item, "-A") == 0)
- abort = 1;
- item = strtok_r(NULL, " ", &tmpPtr);
+ int nostart= 0;
+ int initialstart= 0;
+ int abort= 0;
+ int need_disconnect= 0;
+
+ for (; command_pos < command_list.size(); command_pos++)
+ {
+ const char *item= command_list[command_pos].c_str();
+ if (strcasecmp(item, "-N") == 0)
+ {
+ nostart= 1;
+ continue;
+ }
+ if (strcasecmp(item, "-I") == 0)
+ {
+ initialstart= 1;
+ continue;
}
+ if (strcasecmp(item, "-A") == 0)
+ {
+ abort= 1;
+ continue;
+ }
+ ndbout_c("Invalid option: %s. Expecting -A,-N or -I after RESTART",
+ item);
+ return;
}
- if(all) {
- result = ndb_mgm_restart2(m_mgmsrv, 0, NULL, initialstart, nostart, abort);
- } else {
- int v[1];
- v[0] = processId;
- result = ndb_mgm_restart2(m_mgmsrv, 1, v, initialstart, nostart, abort);
- }
-
+ result= ndb_mgm_restart3(m_mgmsrv, no_of_nodes, node_ids,
+ initialstart, nostart, abort, &need_disconnect);
+
if (result <= 0) {
- ndbout.println("Restart failed.", result);
+ ndbout_c("Restart failed.");
printError();
- } else
+ }
+ else
+ {
+ if (node_ids == 0)
+ ndbout_c("NDB Cluster is being restarted.");
+ else
{
- if(all)
- ndbout << "NDB Cluster is being restarted." << endl;
- else
- ndbout_c("Node %d is being restarted.", processId);
+ ndbout << "Node";
+ for (int i= 0; i < no_of_nodes; i++)
+ ndbout << " " << node_ids[i];
+ ndbout_c(" is being restarted");
}
+ if(need_disconnect)
+ disconnect();
+ }
}
void
diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp
index 9128df4f978..ba5d0308f1f 100644
--- a/ndb/src/mgmclient/main.cpp
+++ b/ndb/src/mgmclient/main.cpp
@@ -90,13 +90,6 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- return ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_mgm.trace");
-}
static int
read_and_execute(int _try_reconnect)
@@ -139,7 +132,11 @@ int main(int argc, char** argv){
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_mgm.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
exit(ho_error);
char buf[MAXHOSTNAMELEN+10];
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
deleted file mode 100644
index 686155415d5..00000000000
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ /dev/null
@@ -1,345 +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 "CommandInterpreter.hpp"
-
-#include <string.h>
-#include <ctype.h>
-
-#include "MgmtSrvr.hpp"
-#include "MgmtErrorReporter.hpp"
-#include <NdbOut.hpp>
-#include "convertStrToInt.hpp"
-#include <EventLogger.hpp>
-#include <signaldata/SetLogLevelOrd.hpp>
-#include "ConfigInfo.hpp"
-
-#include <version.h>
-#include <m_string.h>
-
-//******************************************************************************
-//******************************************************************************
-CommandInterpreter::CommandInterpreter(MgmtSrvr& mgmtSrvr) :
- _mgmtSrvr(mgmtSrvr) {
-}
-
-
-bool emptyString(const char* s) {
- if (s == NULL) {
- return true;
- }
-
- for (unsigned int i = 0; i < strlen(s); ++i) {
- if (! isspace(s[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-class AutoPtr {
-public:
- AutoPtr(void * ptr) : m_ptr(ptr) {}
- ~AutoPtr() { free(m_ptr);}
-private:
- void * m_ptr;
-};
-
-const char *CommandInterpreter::get_error_text(int err_no)
-{
- return _mgmtSrvr.getErrorText(err_no, m_err_str, sizeof(m_err_str));
-}
-
-//*****************************************************************************
-//*****************************************************************************
-int CommandInterpreter::readAndExecute() {
-
- char* _line = readline_gets();
- char * line;
- if(_line == NULL) {
- ndbout << endl;
- return true;
- }
-
- line = strdup(_line);
-
- AutoPtr ptr(line);
-
- if (emptyString(line)) {
- return true;
- }
-
- for (unsigned int i = 0; i < strlen(line); ++i) {
- line[i] = toupper(line[i]);
- }
-
- // if there is anything in the line proceed
- char* firstToken = strtok(line, " ");
- char* allAfterFirstToken = strtok(NULL, "\0");
-
- if (strcmp(firstToken, "ALL") == 0) {
- analyseAfterFirstToken(-1, allAfterFirstToken);
- }
- else if(strcmp(firstToken, "QUIT") == 0 ||
- strcmp(firstToken, "EXIT") == 0 ||
- strcmp(firstToken, "BYE") == 0){
- return false;
- } else {
- // First token should be a digit, process ID
-
- int processId;
- if (! convert(firstToken, processId)) {
- ndbout << "Invalid command: " << _line << "." << endl;
- return true;
- }
- if (processId < 0) {
- ndbout << "Invalid process ID: " << firstToken << "." << endl;
- return true;
- }
-
- analyseAfterFirstToken(processId, allAfterFirstToken);
-
- } // else
- return true;
-}
-
-
-static const CommandInterpreter::CommandFunctionPair commands[] = {
- { "TRACE", &CommandInterpreter::executeTrace }
- ,{ "LOGIN", &CommandInterpreter::executeLogIn }
- ,{ "LOGOUT", &CommandInterpreter::executeLogOut }
- ,{ "LOGOFF", &CommandInterpreter::executeLogOff }
-};
-
-
-//*****************************************************************************
-//*****************************************************************************
-void
-CommandInterpreter::analyseAfterFirstToken(int processId,
- char* allAfterFirstToken) {
-
- if (emptyString(allAfterFirstToken)) {
- if (processId == -1) {
- ndbout << "Expected a command after ALL." << endl;
- }
- else {
- ndbout << "Expected a command after process ID." << endl;
- }
- return;
- }
-
-
- char* secondToken = strtok(allAfterFirstToken, " ");
- char* allAfterSecondToken = strtok(NULL, "\0");
-
- const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair);
- ExecuteFunction fun = 0;
- const char * command = 0;
- for(int i = 0; i<tmpSize; i++){
- if(strcmp(secondToken, commands[i].command) == 0){
- fun = commands[i].executeFunction;
- command = commands[i].command;
- break;
- }
- }
-
- if(fun == 0){
- ndbout << "Invalid command: " << secondToken << "." << endl;
- return;
- }
-
- if(processId == -1){
- executeForAll(command, fun, allAfterSecondToken);
- } else {
- ndbout << "Executing " << command << " on node: "
- << processId << endl << endl;
- (this->*fun)(processId, allAfterSecondToken, false);
- ndbout << endl;
- }
-}
-
-void
-CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
- const char * allAfterSecondToken){
-
- NodeId nodeId = 0;
- while(_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
- ndbout << "Executing " << cmd << " on node: "
- << nodeId << endl << endl;
- (this->*fun)(nodeId, allAfterSecondToken, true);
- ndbout << endl;
- }
-}
-
-//*****************************************************************************
-//*****************************************************************************
-bool CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
- Vector<BaseString>& blocks) {
-
- // Parse: [BLOCK = {ALL|<blockName>+}]
-
- if (emptyString(allAfterLog)) {
- return true;
- }
-
- // Copy allAfterLog since strtok will modify it
- char* newAllAfterLog = strdup(allAfterLog);
- char* firstTokenAfterLog = strtok(newAllAfterLog, " ");
- for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) {
- firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
- }
-
- if (strcmp(firstTokenAfterLog, "BLOCK") != 0) {
- ndbout << "Unexpected value: " << firstTokenAfterLog
- << ". Expected BLOCK." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- char* allAfterFirstToken = strtok(NULL, "\0");
- if (emptyString(allAfterFirstToken)) {
- ndbout << "Expected =." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
- if (strcmp(secondTokenAfterLog, "=") != 0) {
- ndbout << "Unexpected value: " << secondTokenAfterLog
- << ". Expected =." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- char* blockName = strtok(NULL, " ");
- bool all = false;
- if (blockName != NULL && (strcmp(blockName, "ALL") == 0)) {
- all = true;
- }
- while (blockName != NULL) {
- blocks.push_back(BaseString(blockName));
- blockName = strtok(NULL, " ");
- }
-
- if (blocks.size() == 0) {
- ndbout << "No block specified." << endl;
- free(newAllAfterLog);
- return false;
- }
- if (blocks.size() > 1 && all) {
- // More than "ALL" specified
- ndbout << "Nothing expected after ALL." << endl;
- free(newAllAfterLog);
- return false;
- }
-
- free(newAllAfterLog);
- return true;
-}
-
-void CommandInterpreter::executeLogIn(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- Vector<BaseString> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
-}
-
-//******************************************************************************
-//******************************************************************************
-void CommandInterpreter::executeLogOut(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- Vector<BaseString> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out, blocks);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
-
-}
-
-
-//******************************************************************************
-//******************************************************************************
-void CommandInterpreter::executeLogOff(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- Vector<BaseString> blocks;
- if (! parseBlockSpecification(parameters, blocks)) {
- return;
- }
-
-
- int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off, blocks);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
-
-}
-
-void CommandInterpreter::executeTrace(int processId,
- const char* parameters, bool all) {
-
- (void)all; // Don't want compiler warning
-
- if (emptyString(parameters)) {
- ndbout << "Missing trace number." << endl;
- return;
- }
-
- char* newpar = strdup(parameters);
- char* firstParameter = strtok(newpar, " ");
-
-
- int traceNo;
- if (! convert(firstParameter, traceNo)) {
- ndbout << "Expected an integer." << endl;
- free(newpar);
- return;
- }
-
- char* allAfterFirstParameter = strtok(NULL, "\0");
-
- if (! emptyString(allAfterFirstParameter)) {
- ndbout << "Nothing expected after trace number." << endl;
- free(newpar);
- return;
- }
-
- int result = _mgmtSrvr.setTraceNo(processId, traceNo);
- if (result != 0) {
- ndbout << get_error_text(result) << endl;
- }
- free(newpar);
-}
diff --git a/ndb/src/mgmsrv/CommandInterpreter.hpp b/ndb/src/mgmsrv/CommandInterpreter.hpp
deleted file mode 100644
index 6b67d1a5a5f..00000000000
--- a/ndb/src/mgmsrv/CommandInterpreter.hpp
+++ /dev/null
@@ -1,92 +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 CommandInterpreter_H
-#define CommandInterpreter_H
-
-#include <ndb_global.h>
-#include <Vector.hpp>
-#include <BaseString.hpp>
-
-class MgmtSrvr;
-
-class CommandInterpreter {
-public:
- CommandInterpreter(MgmtSrvr& mgmtSrvr);
- int readAndExecute();
-
-private:
- char m_err_str[1024];
- const char *get_error_text(int err_no);
-
- char *readline_gets ()
- {
- static char linebuffer[254];
- static char *line_read = (char *)NULL;
-
- /* If the buffer has already been allocated, return the memory
- to the free pool. */
- if (line_read)
- {
- free (line_read);
- line_read = (char *)NULL;
- }
-
- /* Get a line from the user. */
- fputs("ndb_mgmd> ", stdout);
- linebuffer[sizeof(linebuffer)-1]=0;
- line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
- if (line_read == linebuffer) {
- char *q=linebuffer;
- while (*q > 31) q++;
- *q=0;
- line_read= strdup(linebuffer);
- }
- return (line_read);
- }
-
- void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
- bool parseBlockSpecification(const char* allAfterLog,
- Vector<BaseString>& blocks);
-
-public:
- void executeTrace(int processId, const char* parameters, bool all);
- void executeLogIn(int processId, const char* parameters, bool all);
- void executeLogOut(int processId, const char* parameters, bool all);
- void executeLogOff(int processId, const char* parameters, bool all);
-
-public:
- typedef void (CommandInterpreter::* ExecuteFunction)(int processId,
- const char * param,
- bool all);
-
- struct CommandFunctionPair {
- const char * command;
- ExecuteFunction executeFunction;
- };
-private:
- /**
- *
- */
- void executeForAll(const char * cmd, ExecuteFunction fun, const char * param);
-
- /**
- * Management server to use when executing commands
- */
- MgmtSrvr& _mgmtSrvr;
-};
-
-#endif // CommandInterpreter_H
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index 0e674ab4e70..ab4f2b413b3 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -58,7 +58,6 @@ ConfigInfo::m_sectionNameAliases[]={
const char*
ConfigInfo::m_sectionNames[]={
"SYSTEM",
- "EXTERNAL SYSTEM",
"COMPUTER",
DB_TOKEN,
@@ -79,9 +78,7 @@ sizeof(m_sectionNames)/sizeof(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 checkConnectionSupport(InitConfigFileParser::Context & ctx, const char *);
static bool transformConnection(InitConfigFileParser::Context & ctx, const char *);
static bool applyDefaultValues(InitConfigFileParser::Context & ctx, const char *);
@@ -94,7 +91,6 @@ 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 *);
static bool fixFileSystemPath(InitConfigFileParser::Context & ctx, const char * data);
@@ -105,7 +101,6 @@ static bool checkLocalhostHostnameMix(InitConfigFileParser::Context & ctx, const
const ConfigInfo::SectionRule
ConfigInfo::m_SectionRules[] = {
{ "SYSTEM", transformSystem, 0 },
- { "EXTERNAL SYSTEM", transformExternalSystem, 0 },
{ "COMPUTER", transformComputer, 0 },
{ DB_TOKEN, transformNode, 0 },
@@ -151,20 +146,13 @@ ConfigInfo::m_SectionRules[] = {
{ "TCP", fixPortNumber, 0 }, // has to come after fixHostName
{ "SHM", fixPortNumber, 0 }, // has to come after fixHostName
{ "SCI", fixPortNumber, 0 }, // has to come after fixHostName
- { "SHM", fixShmKey, 0 },
- /**
- * fixExtConnection must be after fixNodeId
- */
- { "TCP", fixExtConnection, 0 },
- { "SHM", fixExtConnection, 0 },
- { "SCI", fixExtConnection, 0 },
- { "OSE", fixExtConnection, 0 },
-
{ "*", applyDefaultValues, "user" },
{ "*", fixDepricated, 0 },
{ "*", applyDefaultValues, "system" },
+ { "SHM", fixShmKey, 0 }, // has to come after apply default values
+
{ DB_TOKEN, checkLocalhostHostnameMix, 0 },
{ API_TOKEN, checkLocalhostHostnameMix, 0 },
{ MGM_TOKEN, checkLocalhostHostnameMix, 0 },
@@ -174,9 +162,6 @@ ConfigInfo::m_SectionRules[] = {
{ DB_TOKEN, checkDbConstraints, 0 },
- /**
- * checkConnectionConstraints must be after fixExtConnection
- */
{ "TCP", checkConnectionConstraints, 0 },
{ "SHM", checkConnectionConstraints, 0 },
{ "SCI", checkConnectionConstraints, 0 },
@@ -214,9 +199,6 @@ static bool add_node_connections(Vector<ConfigInfo::ConfigRuleSection>&sections,
static bool set_connection_priorities(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);
@@ -226,7 +208,6 @@ ConfigInfo::m_ConfigRules[] = {
{ sanity_checks, 0 },
{ add_node_connections, 0 },
{ set_connection_priorities, 0 },
- { add_server_ports, 0 },
{ check_node_vs_replicas, 0 },
{ 0, 0 }
};
@@ -242,6 +223,9 @@ struct DepricationTransform {
static
const DepricationTransform f_deprication[] = {
{ DB_TOKEN, "Discless", "Diskless", 0, 1 },
+ { DB_TOKEN, "Id", "NodeId", 0, 1 },
+ { API_TOKEN, "Id", "NodeId", 0, 1 },
+ { MGM_TOKEN, "Id", "NodeId", 0, 1 },
{ 0, 0, 0, 0, 0}
};
@@ -406,9 +390,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0, 0 },
{
- CFG_NODE_ID,
+ KEY_INTERNAL,
"Id",
DB_TOKEN,
+ "",
+ ConfigInfo::CI_DEPRICATED,
+ false,
+ ConfigInfo::CI_INT,
+ MANDATORY,
+ "1",
+ STR_VALUE(MAX_NODES) },
+
+ {
+ CFG_NODE_ID,
+ "NodeId",
+ DB_TOKEN,
"Number identifying the database node ("DB_TOKEN_PRINT")",
ConfigInfo::CI_USED,
false,
@@ -1098,6 +1094,18 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
"15" },
{
+ CFG_LOGLEVEL_CONGESTION,
+ "LogLevelCongestion",
+ DB_TOKEN,
+ "Congestion info printed on stdout",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ "0",
+ "0",
+ "15" },
+
+ {
CFG_LOGLEVEL_ERROR,
"LogLevelError",
DB_TOKEN,
@@ -1245,9 +1253,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0, 0 },
{
- CFG_NODE_ID,
+ KEY_INTERNAL,
"Id",
API_TOKEN,
+ "",
+ ConfigInfo::CI_DEPRICATED,
+ false,
+ ConfigInfo::CI_INT,
+ MANDATORY,
+ "1",
+ STR_VALUE(MAX_NODES) },
+
+ {
+ CFG_NODE_ID,
+ "NodeId",
+ API_TOKEN,
"Number identifying application node ("API_TOKEN_PRINT")",
ConfigInfo::CI_USED,
false,
@@ -1376,9 +1396,21 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
0, 0 },
{
- CFG_NODE_ID,
+ KEY_INTERNAL,
"Id",
MGM_TOKEN,
+ "",
+ ConfigInfo::CI_DEPRICATED,
+ false,
+ ConfigInfo::CI_INT,
+ MANDATORY,
+ "1",
+ STR_VALUE(MAX_NODES) },
+
+ {
+ CFG_NODE_ID,
+ "NodeId",
+ MGM_TOKEN,
"Number identifying the management server node ("MGM_TOKEN_PRINT")",
ConfigInfo::CI_USED,
false,
@@ -1540,6 +1572,17 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
"0", "200" },
{
+ CFG_CONNECTION_NODE_ID_SERVER,
+ "NodeIdServer",
+ "TCP",
+ "",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ MANDATORY,
+ "1", "63" },
+
+ {
CFG_CONNECTION_SEND_SIGNAL_ID,
"SendSignalId",
"TCP",
@@ -1728,6 +1771,17 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
"0", "200" },
{
+ CFG_CONNECTION_NODE_ID_SERVER,
+ "NodeIdServer",
+ "SHM",
+ "",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ MANDATORY,
+ "1", "63" },
+
+ {
CFG_CONNECTION_SEND_SIGNAL_ID,
"SendSignalId",
"SHM",
@@ -1760,7 +1814,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::CI_USED,
false,
ConfigInfo::CI_INT,
- "0",
+ UNDEFINED,
"0",
STR_VALUE(MAX_INT_RNIL) },
@@ -1849,6 +1903,17 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
"0", "200" },
{
+ CFG_CONNECTION_NODE_ID_SERVER,
+ "NodeIdServer",
+ "SCI",
+ "",
+ ConfigInfo::CI_USED,
+ false,
+ ConfigInfo::CI_INT,
+ MANDATORY,
+ "1", "63" },
+
+ {
CFG_CONNECTION_HOSTNAME_1,
"HostName1",
"SCI",
@@ -2177,11 +2242,11 @@ ConfigInfo::ConfigInfo()
if (!m_info.getCopy(param._section, &section)) {
Properties newsection(true);
m_info.put(param._section, &newsection);
+
+ // Get copy of section
+ m_info.getCopy(param._section, &section);
}
-
- // Get copy of section
- m_info.getCopy(param._section, &section);
-
+
// Create pinfo (parameter info) entry
Properties pinfo(true);
pinfo.put("Id", param._paramId);
@@ -2235,6 +2300,7 @@ ConfigInfo::ConfigInfo()
// Replace section with modified section
m_info.put(param._section, section, true);
+ delete section;
if(param._type != ConfigInfo::CI_SECTION){
Properties * p;
@@ -2516,29 +2582,32 @@ void ConfigInfo::print(const Properties * section,
bool
transformNode(InitConfigFileParser::Context & ctx, const char * data){
- Uint32 id;
- if(!ctx.m_currentSection->get("Id", &id)){
+ Uint32 id, line;
+ if(!ctx.m_currentSection->get("NodeId", &id) && !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))
+ while (ctx.m_userProperties.get("AllocatedNodeId_", id, &line))
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);
+ if (id != nextNodeId)
+ {
+ fprintf(stderr,"Cluster configuration warning line %d: "
+ "Could not use next node id %d for section [%s], "
+ "using next unused node id %d.\n",
+ ctx.m_sectionLineno, nextNodeId, ctx.fname, id);
+ }
+ ctx.m_currentSection->put("NodeId", id);
+ } else if(ctx.m_userProperties.get("AllocatedNodeId_", id, &line)) {
+ ctx.reportError("Duplicate nodeid in section "
+ "[%s] starting at line: %d. Previously used on line %d.",
+ ctx.fname, ctx.m_sectionLineno, line);
return false;
}
- ctx.m_userProperties.put("AllocatedNodeId_", id, id);
+ // next node id _always_ next numbers after last used id
+ ctx.m_userProperties.put("NextNodeId", id+1, true);
+
+ ctx.m_userProperties.put("AllocatedNodeId_", id, ctx.m_sectionLineno);
BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "Node_%d", id);
ctx.m_currentSection->put("Type", ctx.fname);
@@ -2652,38 +2721,6 @@ fixBackupDataDir(InitConfigFileParser::Context & ctx, const char * data){
return false;
}
-bool
-transformExtNode(InitConfigFileParser::Context & ctx, const char * data){
-
- Uint32 id;
- const char * systemName;
-
- if(!ctx.m_currentSection->get("Id", &id)){
- ctx.reportError("Mandatory parameter 'Id' missing from section "
- "[%s] starting at line: %d",
- ctx.fname, ctx.m_sectionLineno);
- return false;
- }
-
- if(!ctx.m_currentSection->get("System", &systemName)){
- ctx.reportError("Mandatory parameter 'System' missing from section "
- "[%s] starting at line: %d",
- ctx.fname, ctx.m_sectionLineno);
- return false;
- }
-
- ctx.m_currentSection->put("Type", ctx.fname);
-
- Uint32 nodes = 0;
- ctx.m_userProperties.get("ExtNoOfNodes", &nodes);
- require(ctx.m_userProperties.put("ExtNoOfNodes",++nodes, true));
-
- BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "EXTERNAL SYSTEM_%s:Node_%d",
- systemName, id);
-
- return true;
-}
-
/**
* Connection rule: Check support of connection
*/
@@ -2760,23 +2797,6 @@ transformSystem(InitConfigFileParser::Context & ctx, const char * data){
}
/**
- * External system rule: Just add it
- */
-bool
-transformExternalSystem(InitConfigFileParser::Context & ctx, const char * data){
- const char * name;
- if(!ctx.m_currentSection->get("Name", &name)){
- ctx.reportError("Mandatory parameter Name missing from section "
- "[%s] starting at line: %d",
- ctx.fname, ctx.m_sectionLineno);
- return false;
- }
- BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "EXTERNAL SYSTEM_%s", name);
-
- return true;
-}
-
-/**
* Computer rule: Update "NoOfComputers", add "Type"
*/
bool
@@ -2952,87 +2972,6 @@ static bool fixNodeId(InitConfigFileParser::Context & ctx, const char * data)
}
/**
- * @returns true if connection is external (one node is external)
- * Also returns:
- * - name of external system in parameter extSystemName, and
- * - nodeId of external node in parameter extSystemNodeId.
- */
-static bool
-isExtConnection(InitConfigFileParser::Context & ctx,
- const char **extSystemName, Uint32 * extSystemNodeId){
-
- Uint32 nodeId1, nodeId2;
-
- if (ctx.m_currentSection->contains("System1") &&
- ctx.m_currentSection->get("System1", extSystemName) &&
- ctx.m_currentSection->get("NodeId1", &nodeId1)) {
- *extSystemNodeId = nodeId1;
- return true;
- }
-
- if (ctx.m_currentSection->contains("System2") &&
- ctx.m_currentSection->get("System2", extSystemName) &&
- ctx.m_currentSection->get("NodeId2", &nodeId2)) {
- *extSystemNodeId = nodeId2;
- return true;
- }
-
- return false;
-}
-
-/**
- * External Connection Rule:
- * If connection is to an external system, then move connection into
- * external system configuration (i.e. a sub-property).
- */
-static bool
-fixExtConnection(InitConfigFileParser::Context & ctx, const char * data){
-
- const char * extSystemName;
- Uint32 extSystemNodeId;
-
- if (isExtConnection(ctx, &extSystemName, &extSystemNodeId)) {
-
- Uint32 connections = 0;
- ctx.m_userProperties.get("ExtNoOfConnections", &connections);
- require(ctx.m_userProperties.put("ExtNoOfConnections",++connections, true));
-
- char tmpLine1[MAX_LINE_LENGTH];
- BaseString::snprintf(tmpLine1, MAX_LINE_LENGTH, "Connection_%d", connections-1);
-
- /**
- * Section: EXTERNAL SYSTEM_<Ext System Name>
- */
- char extSystemPropName[MAX_LINE_LENGTH];
- strncpy(extSystemPropName, "EXTERNAL SYSTEM_", MAX_LINE_LENGTH);
- strncat(extSystemPropName, extSystemName, MAX_LINE_LENGTH);
- strncat(extSystemPropName, ":", MAX_LINE_LENGTH);
- strncat(extSystemPropName, tmpLine1, MAX_LINE_LENGTH);
-
- /**
- * Increase number of external connections for the system
- *
- * @todo Limitation: Only one external system is allowed
- */
- require(ctx.m_userProperties.put("ExtSystem", extSystemName, true));
-
- /**
- * Make sure section is stored in right place
- */
- strncpy(ctx.pname, extSystemPropName, MAX_LINE_LENGTH);
-
- /**
- * Since this is an external connection,
- * decrease number of internal connections
- */
- require(ctx.m_userProperties.get("NoOfConnections", &connections));
- require(ctx.m_userProperties.put("NoOfConnections", --connections, true));
- }
-
- return true;
-}
-
-/**
* Connection rule: Fix hostname
*
* Unless Hostname is not already specified, do steps:
@@ -3074,7 +3013,7 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
DBUG_ENTER("fixPortNumber");
- Uint32 id1= 0, id2= 0;
+ Uint32 id1, id2;
const char *hostName1;
const char *hostName2;
require(ctx.m_currentSection->get("NodeId1", &id1));
@@ -3084,19 +3023,48 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
DBUG_PRINT("info",("NodeId1=%d HostName1=\"%s\"",id1,hostName1));
DBUG_PRINT("info",("NodeId2=%d HostName2=\"%s\"",id2,hostName2));
- if (id1 > id2) {
- Uint32 tmp= id1;
- const char *tmp_name= hostName1;
- hostName1= hostName2;
- id1= id2;
- hostName2= tmp_name;
- id2= tmp;
+ const Properties *node1, *node2;
+ require(ctx.m_config->get("Node", id1, &node1));
+ require(ctx.m_config->get("Node", id2, &node2));
+
+ const char *type1, *type2;
+ require(node1->get("Type", &type1));
+ require(node2->get("Type", &type2));
+
+ /* add NodeIdServer info */
+ {
+ Uint32 nodeIdServer = id1 < id2 ? id1 : id2;
+ if(strcmp(type1, API_TOKEN) == 0 || strcmp(type2, MGM_TOKEN) == 0)
+ nodeIdServer = id2;
+ else if(strcmp(type2, API_TOKEN) == 0 || strcmp(type1, MGM_TOKEN) == 0)
+ nodeIdServer = id1;
+ ctx.m_currentSection->put("NodeIdServer", nodeIdServer);
+
+ if (id2 == nodeIdServer) {
+ {
+ const char *tmp= hostName1;
+ hostName1= hostName2;
+ hostName2= tmp;
+ }
+ {
+ Uint32 tmp= id1;
+ id1= id2;
+ id2= tmp;
+ }
+ {
+ const Properties *tmp= node1;
+ node1= node2;
+ node2= tmp;
+ }
+ {
+ const char *tmp= type1;
+ type1= type2;
+ type2= tmp;
+ }
+ }
}
- const Properties * node;
- require(ctx.m_config->get("Node", id1, &node));
BaseString hostname(hostName1);
- // require(node->get("HostName", hostname));
if (hostname.c_str()[0] == 0) {
ctx.reportError("Hostname required on nodeid %d since it will "
@@ -3105,29 +3073,43 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
}
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);
- }
+ if(strcmp(type1, MGM_TOKEN)==0)
+ node1->get("PortNumber",&port);
+ else if(strcmp(type2, MGM_TOKEN)==0)
+ node2->get("PortNumber",&port);
+ if (!port &&
+ !node1->get("ServerPort", &port) &&
+ !ctx.m_userProperties.get("ServerPort_", id1, &port))
+ {
Uint32 base= 0;
- if (!ctx.m_userProperties.get("ServerPortBase", &base)){
- if(!(ctx.m_userDefaults &&
+ /*
+ * If the connection doesn't involve an mgm server,
+ * and a default port number has been set, behave the old
+ * way of allocating port numbers for transporters.
+ */
+ if(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base))
+ {
+ 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);
+ }
+
+ if (!ctx.m_userProperties.get("ServerPortBase", &base)){
+ if(!(ctx.m_userDefaults &&
ctx.m_userDefaults->get("PortNumber", &base)) &&
- !ctx.m_systemDefaults->get("PortNumber", &base)) {
- base= strtoll(NDB_TCP_BASE_PORT,0,0);
- // ctx.reportError("Cannot retrieve base port number");
- // return false;
+ !ctx.m_systemDefaults->get("PortNumber", &base)) {
+ base= strtoll(NDB_TCP_BASE_PORT,0,0);
+ }
+ ctx.m_userProperties.put("ServerPortBase", base);
}
- ctx.m_userProperties.put("ServerPortBase", base);
+
+ port= base + adder;
+ ctx.m_userProperties.put("ServerPort_", id1, port);
}
- port= base + adder;
- ctx.m_userProperties.put("ServerPort_", id1, port);
}
if(ctx.m_currentSection->contains("PortNumber")) {
@@ -3140,6 +3122,7 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
{
ctx.m_currentSection->put("PortNumber", port);
}
+
DBUG_PRINT("info", ("connection %d-%d port %d host %s",
id1, id2, port, hostname.c_str()));
@@ -3247,11 +3230,6 @@ checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
ctx.m_currentSection->get("NodeId1", &id1);
ctx.m_currentSection->get("NodeId2", &id2);
- // If external connection, just accept it
- if (ctx.m_currentSection->contains("System1") ||
- ctx.m_currentSection->contains("System2"))
- return true;
-
if(id1 == id2){
ctx.reportError("Illegal connection from node to itself"
" - [%s] starting at line: %d",
@@ -3284,12 +3262,10 @@ checkConnectionConstraints(InitConfigFileParser::Context & ctx, const char *){
* Report error if the following are true
* -# None of the nodes is of type DB
* -# Not both of them are MGMs
- * -# None of them contain a "SystemX" name
*/
if((strcmp(type1, DB_TOKEN) != 0 && strcmp(type2, DB_TOKEN) != 0) &&
- !(strcmp(type1, MGM_TOKEN) == 0 && strcmp(type2, MGM_TOKEN) == 0) &&
- !ctx.m_currentSection->contains("System1") &&
- !ctx.m_currentSection->contains("System2")){
+ !(strcmp(type1, MGM_TOKEN) == 0 && strcmp(type2, MGM_TOKEN) == 0))
+ {
ctx.reportError("Invalid connection between node %d (%s) and node %d (%s)"
" - [%s] starting at line: %d",
id1, type1, id2, type2,
@@ -3334,6 +3310,7 @@ transform(InitConfigFileParser::Context & ctx,
PropertiesType oldType;
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::CI_INT || newType == ConfigInfo::CI_INT64 || newType == ConfigInfo::CI_BOOL))){
ndbout << "oldType: " << (int)oldType << ", newType: " << (int)newType << endl;
@@ -3378,11 +3355,11 @@ fixDepricated(InitConfigFileParser::Context & ctx, const char * data){
if(strcmp(p->m_section, ctx.fname) == 0){
double mul = p->m_mul;
double add = p->m_add;
- if(strcmp(name, p->m_oldName) == 0){
+ if(strcasecmp(name, p->m_oldName) == 0){
if(!transform(ctx, tmp, name, p->m_newName, add, mul)){
return false;
}
- } else if(strcmp(name, p->m_newName) == 0) {
+ } else if(strcasecmp(name, p->m_newName) == 0) {
if(!transform(ctx, tmp, name, p->m_oldName, -add/mul,1.0/mul)){
return false;
}
@@ -3661,45 +3638,6 @@ static bool set_connection_priorities(Vector<ConfigInfo::ConfigRuleSection>&sect
DBUG_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_TCP_BASE_PORT;
-
- 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_TOKEN) == 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,
diff --git a/ndb/src/mgmsrv/InitConfigFileParser.cpp b/ndb/src/mgmsrv/InitConfigFileParser.cpp
index b2c290df9fc..f937daf8620 100644
--- a/ndb/src/mgmsrv/InitConfigFileParser.cpp
+++ b/ndb/src/mgmsrv/InitConfigFileParser.cpp
@@ -163,6 +163,13 @@ InitConfigFileParser::parseConfig(FILE * file) {
ctx.reportError("Could not store section of configuration file.");
return 0;
}
+
+ return run_config_rules(ctx);
+}
+
+Config*
+InitConfigFileParser::run_config_rules(Context& ctx)
+{
for(size_t i = 0; ConfigInfo::m_ConfigRules[i].m_configRule != 0; i++){
ctx.type = InitConfigFileParser::Undefined;
ctx.m_currentSection = 0;
@@ -270,10 +277,10 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line)
}
if (status == ConfigInfo::CI_DEPRICATED) {
const char * desc = m_info->getDescription(ctx.m_currentInfo, fname);
- if(desc){
+ if(desc && desc[0]){
ctx.reportWarning("[%s] %s is depricated, use %s instead",
ctx.fname, fname, desc);
- } else {
+ } else if (desc == 0){
ctx.reportWarning("[%s] %s is depricated", ctx.fname, fname);
}
}
@@ -597,3 +604,353 @@ InitConfigFileParser::Context::reportWarning(const char * fmt, ...){
fprintf(m_errstream, "Warning line %d: %s\n",
m_lineno, buf);
}
+
+#include <my_sys.h>
+#include <my_getopt.h>
+
+static int order = 1;
+static
+my_bool
+parse_mycnf_opt(int, const struct my_option * opt, char * value)
+{
+ if(opt->comment)
+ ((struct my_option *)opt)->app_type++;
+ else
+ ((struct my_option *)opt)->app_type = order++;
+ return 0;
+}
+
+bool
+InitConfigFileParser::store_in_properties(Vector<struct my_option>& options,
+ InitConfigFileParser::Context& ctx,
+ const char * name)
+{
+ for(unsigned i = 0; i<options.size(); i++)
+ {
+ if(options[i].comment &&
+ options[i].app_type &&
+ strcmp(options[i].comment, name) == 0)
+ {
+ Uint64 value_int;
+ switch(options[i].var_type){
+ case GET_INT:
+ value_int = *(Uint32*)options[i].value;
+ break;
+ case GET_LL:
+ value_int = *(Uint64*)options[i].value;
+ break;
+ case GET_STR:
+ ctx.m_currentSection->put(options[i].name, *(char**)options[i].value);
+ continue;
+ default:
+ abort();
+ }
+
+ const char * fname = options[i].name;
+ if (!m_info->verify(ctx.m_currentInfo, fname, value_int)) {
+ ctx.reportError("Illegal value %lld for parameter %s.\n"
+ "Legal values are between %Lu and %Lu",
+ value_int, fname,
+ m_info->getMin(ctx.m_currentInfo, fname),
+ m_info->getMax(ctx.m_currentInfo, fname));
+ return false;
+ }
+ if (options[i].var_type == GET_INT)
+ ctx.m_currentSection->put(options[i].name, (Uint32)value_int);
+ else
+ ctx.m_currentSection->put(options[i].name, value_int);
+ }
+ }
+ return true;
+}
+
+bool
+InitConfigFileParser::handle_mycnf_defaults(Vector<struct my_option>& options,
+ InitConfigFileParser::Context& ctx,
+ const char * name)
+{
+ strcpy(ctx.fname, name);
+ ctx.type = InitConfigFileParser::DefaultSection;
+ ctx.m_currentSection = new Properties(true);
+ ctx.m_userDefaults = NULL;
+ require((ctx.m_currentInfo = m_info->getInfo(ctx.fname)) != 0);
+ require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname)) != 0);
+ if(store_in_properties(options, ctx, name))
+ return storeSection(ctx);
+ return false;
+}
+
+static
+int
+load_defaults(Vector<struct my_option>& options, const char* groups[])
+{
+ int argc = 1;
+ const char * argv[] = { "ndb_mgmd", 0, 0, 0, 0 };
+ BaseString file;
+ BaseString extra_file;
+ BaseString group_suffix;
+
+ const char *save_file = defaults_file;
+ char *save_extra_file = defaults_extra_file;
+ const char *save_group_suffix = defaults_group_suffix;
+
+ if (defaults_file)
+ {
+ file.assfmt("--defaults-file=%s", defaults_file);
+ argv[argc++] = file.c_str();
+ }
+
+ if (defaults_extra_file)
+ {
+ extra_file.assfmt("--defaults-extra-file=%s", defaults_extra_file);
+ argv[argc++] = extra_file.c_str();
+ }
+
+ if (defaults_group_suffix)
+ {
+ group_suffix.assfmt("--defaults-group-suffix=%s", defaults_group_suffix);
+ argv[argc++] = group_suffix.c_str();
+ }
+
+ char ** tmp = (char**)argv;
+ int ret = load_defaults("my", groups, &argc, &tmp);
+
+ defaults_file = save_file;
+ defaults_extra_file = save_extra_file;
+ defaults_group_suffix = save_group_suffix;
+
+ if (ret == 0)
+ {
+ return handle_options(&argc, &tmp, options.getBase(), parse_mycnf_opt);
+ }
+
+ return ret;
+}
+
+bool
+InitConfigFileParser::load_mycnf_groups(Vector<struct my_option> & options,
+ InitConfigFileParser::Context& ctx,
+ const char * name,
+ const char *groups[])
+{
+ unsigned i;
+ Vector<struct my_option> copy;
+ for(i = 0; i<options.size(); i++)
+ {
+ if(options[i].comment && strcmp(options[i].comment, name) == 0)
+ {
+ options[i].app_type = 0;
+ copy.push_back(options[i]);
+ }
+ }
+
+ struct my_option end;
+ bzero(&end, sizeof(end));
+ copy.push_back(end);
+
+ if (load_defaults(copy, groups))
+ return false;
+
+ return store_in_properties(copy, ctx, name);
+}
+
+Config *
+InitConfigFileParser::parse_mycnf()
+{
+ int i;
+ Config * res = 0;
+ Vector<struct my_option> options;
+ for(i = 0; i<ConfigInfo::m_NoOfParams; i++)
+ {
+ {
+ struct my_option opt;
+ bzero(&opt, sizeof(opt));
+ const ConfigInfo::ParamInfo& param = ConfigInfo::m_ParamInfo[i];
+ switch(param._type){
+ case ConfigInfo::CI_BOOL:
+ opt.value = (gptr*)malloc(sizeof(int));
+ opt.var_type = GET_INT;
+ break;
+ case ConfigInfo::CI_INT:
+ opt.value = (gptr*)malloc(sizeof(int));
+ opt.var_type = GET_INT;
+ break;
+ case ConfigInfo::CI_INT64:
+ opt.value = (gptr*)malloc(sizeof(Int64));
+ opt.var_type = GET_LL;
+ break;
+ case ConfigInfo::CI_STRING:
+ opt.value = (gptr*)malloc(sizeof(char *));
+ opt.var_type = GET_STR;
+ break;
+ default:
+ continue;
+ }
+ opt.name = param._fname;
+ opt.id = 256;
+ opt.app_type = 0;
+ opt.arg_type = REQUIRED_ARG;
+ opt.comment = param._section;
+ options.push_back(opt);
+ }
+ }
+
+ struct my_option *ndbd, *ndb_mgmd, *mysqld, *api;
+
+ /**
+ * Add ndbd, ndb_mgmd, api/mysqld
+ */
+ {
+ struct my_option opt;
+ bzero(&opt, sizeof(opt));
+ opt.name = "ndbd";
+ opt.id = 256;
+ opt.value = (gptr*)malloc(sizeof(char*));
+ opt.var_type = GET_STR;
+ opt.arg_type = REQUIRED_ARG;
+ options.push_back(opt);
+ ndbd = &options.back();
+
+ opt.name = "ndb_mgmd";
+ opt.id = 256;
+ opt.value = (gptr*)malloc(sizeof(char*));
+ opt.var_type = GET_STR;
+ opt.arg_type = REQUIRED_ARG;
+ options.push_back(opt);
+ ndb_mgmd = &options.back();
+
+ opt.name = "mysqld";
+ opt.id = 256;
+ opt.value = (gptr*)malloc(sizeof(char*));
+ opt.var_type = GET_STR;
+ opt.arg_type = REQUIRED_ARG;
+ options.push_back(opt);
+ mysqld = &options.back();
+
+ opt.name = "api";
+ opt.id = 256;
+ opt.value = (gptr*)malloc(sizeof(char*));
+ opt.var_type = GET_STR;
+ opt.arg_type = REQUIRED_ARG;
+ options.push_back(opt);
+ api = &options.back();
+
+ bzero(&opt, sizeof(opt));
+ options.push_back(opt);
+ }
+
+
+ Context ctx(m_info, m_errstream);
+ const char *groups[]= { "cluster_config", 0 };
+ if (load_defaults(options, groups))
+ goto end;
+
+ ctx.m_lineno = 0;
+ if(!handle_mycnf_defaults(options, ctx, "DB"))
+ goto end;
+ if(!handle_mycnf_defaults(options, ctx, "API"))
+ goto end;
+ if(!handle_mycnf_defaults(options, ctx, "MGM"))
+ goto end;
+ if(!handle_mycnf_defaults(options, ctx, "TCP"))
+ goto end;
+ if(!handle_mycnf_defaults(options, ctx, "SHM"))
+ goto end;
+ if(!handle_mycnf_defaults(options, ctx, "SCI"))
+ goto end;
+
+ {
+ struct sect { struct my_option* src; const char * name; } sections[] =
+ {
+ { ndb_mgmd, "MGM" }
+ ,{ ndbd, "DB" }
+ ,{ mysqld, "API" }
+ ,{ api, "API" }
+ ,{ 0, 0 }, { 0, 0 }
+ };
+
+ for(i = 0; sections[i].src; i++)
+ {
+ for(int j = i + 1; sections[j].src; j++)
+ {
+ if (sections[j].src->app_type < sections[i].src->app_type)
+ {
+ sect swap = sections[i];
+ sections[i] = sections[j];
+ sections[j] = swap;
+ }
+ }
+ }
+
+ ctx.type = InitConfigFileParser::Section;
+ ctx.m_sectionLineno = ctx.m_lineno;
+ for(i = 0; sections[i].src; i++)
+ {
+ if (sections[i].src->app_type)
+ {
+ strcpy(ctx.fname, sections[i].name);
+ BaseString str(*(char**)sections[i].src->value);
+ Vector<BaseString> list;
+ str.split(list, ",");
+
+ const char * defaults_groups[] = { 0, 0, 0 };
+ for(unsigned j = 0; j<list.size(); j++)
+ {
+ BaseString group_idx;
+ BaseString group_host;
+ group_idx.assfmt("%s.%s.%d", groups[0],
+ sections[i].src->name, j + 1);
+ group_host.assfmt("%s.%s.%s", groups[0],
+ sections[i].src->name, list[j].c_str());
+ defaults_groups[0] = group_idx.c_str();
+ if(list[j].length())
+ defaults_groups[1] = group_host.c_str();
+ else
+ defaults_groups[1] = 0;
+
+ ctx.m_currentSection = new Properties(true);
+ ctx.m_userDefaults = getSection(ctx.fname, ctx.m_defaults);
+ require((ctx.m_currentInfo = m_info->getInfo(ctx.fname)) != 0);
+ require((ctx.m_systemDefaults = m_info->getDefaults(ctx.fname))!= 0);
+ ctx.m_currentSection->put("HostName", list[j].c_str());
+ if(!load_mycnf_groups(options, ctx, sections[i].name,
+ defaults_groups))
+ goto end;
+
+ if(!storeSection(ctx))
+ goto end;
+ }
+ }
+ }
+ }
+
+ res = run_config_rules(ctx);
+
+end:
+ for(i = 0; options[i].name; i++)
+ free(options[i].value);
+
+ return res;
+}
+
+template class Vector<struct my_option>;
+
+#if 0
+struct my_option
+{
+ const char *name; /* Name of the option */
+ int id; /* unique id or short option */
+ const char *comment; /* option comment, for autom. --help */
+ gptr *value; /* The variable value */
+ gptr *u_max_value; /* The user def. max variable value */
+ const char **str_values; /* Pointer to possible values */
+ ulong var_type;
+ enum get_opt_arg_type arg_type;
+ longlong def_value; /* Default value */
+ longlong min_value; /* Min allowed value */
+ longlong max_value; /* Max allowed value */
+ longlong sub_size; /* Subtract this from given value */
+ long block_size; /* Value should be a mult. of this */
+ int app_type; /* To be used by an application */
+};
+#endif
diff --git a/ndb/src/mgmsrv/InitConfigFileParser.hpp b/ndb/src/mgmsrv/InitConfigFileParser.hpp
index 39abf3f6811..616fd5a62fb 100644
--- a/ndb/src/mgmsrv/InitConfigFileParser.hpp
+++ b/ndb/src/mgmsrv/InitConfigFileParser.hpp
@@ -51,6 +51,7 @@ public:
*/
Config * parseConfig(FILE * file);
Config * parseConfig(const char * filename);
+ Config * parse_mycnf();
/**
* Parser context struct
@@ -124,6 +125,21 @@ private:
* Information about parameters (min, max values etc)
*/
ConfigInfo* m_info;
+
+ bool handle_mycnf_defaults(Vector<struct my_option>& options,
+ InitConfigFileParser::Context& ctx,
+ const char * name);
+
+ bool load_mycnf_groups(Vector<struct my_option> & options,
+ InitConfigFileParser::Context& ctx,
+ const char * name,
+ const char *groups[]);
+
+ bool store_in_properties(Vector<struct my_option>& options,
+ InitConfigFileParser::Context& ctx,
+ const char * name);
+
+ Config* run_config_rules(Context& ctx);
};
#endif // InitConfigFileParser_H
diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am
index 50e0b6023ad..7fd3fa66b43 100644
--- a/ndb/src/mgmsrv/Makefile.am
+++ b/ndb/src/mgmsrv/Makefile.am
@@ -16,17 +16,20 @@ ndb_mgmd_SOURCES = \
MgmtSrvrConfig.cpp \
ConfigInfo.cpp \
InitConfigFileParser.cpp \
- Config.cpp \
- CommandInterpreter.cpp
+ Config.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \
-I$(top_srcdir)/ndb/src/mgmapi \
- -I$(top_srcdir)/ndb/src/common/mgmcommon
+ -I$(top_srcdir)/ndb/src/common/mgmcommon \
+ -I$(top_srcdir)/ndb/src/mgmclient
-LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
+LDADD_LOC = $(top_srcdir)/ndb/src/mgmclient/CommandInterpreter.o \
+ $(top_builddir)/ndb/src/libndbclient.la \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
+ $(top_builddir)/strings/libmystrings.a \
+ @readline_link@ \
+ @NDB_SCI_LIBS@ \
@TERMCAP_LIB@
DEFS_LOC = -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index fffd74b9b09..69c0286a1de 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -175,16 +175,16 @@ MgmtSrvr::logLevelThreadRun()
void
MgmtSrvr::startEventLog()
{
+ NdbMutex_Lock(m_configMutex);
+
g_eventLogger.setCategory("MgmSrvr");
- ndb_mgm_configuration_iterator * iter = ndb_mgm_create_configuration_iterator
- ((ndb_mgm_configuration*)_config->m_configValues, CFG_SECTION_NODE);
- if(iter == 0)
- return ;
-
- if(ndb_mgm_find(iter, CFG_NODE_ID, _ownNodeId) != 0){
- ndb_mgm_destroy_iterator(iter);
- return ;
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ if(iter.find(CFG_NODE_ID, _ownNodeId) != 0){
+ NdbMutex_Unlock(m_configMutex);
+ return;
}
const char * tmp;
@@ -194,10 +194,10 @@ MgmtSrvr::startEventLog()
char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
NdbAutoPtr<char> tmp_aptr(clusterLog);
- if(ndb_mgm_get_string_parameter(iter, CFG_LOG_DESTINATION, &tmp) == 0){
+ if(iter.get(CFG_LOG_DESTINATION, &tmp) == 0){
logdest.assign(tmp);
}
- ndb_mgm_destroy_iterator(iter);
+ NdbMutex_Unlock(m_configMutex);
if(logdest.length() == 0 || logdest == "") {
logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6",
@@ -296,15 +296,15 @@ static ErrorItem errorTable[] =
{MgmtSrvr::NOT_POSSIBLE_TO_SEND_CONFIG_UPDATE_TO_PROCESS_TYPE,
"It is not possible to send an update of a configuration variable "
"to this kind of process."},
- {5026, "Node shutdown in progress" },
- {5027, "System shutdown in progress" },
- {5028, "Node shutdown would cause system crash" },
- {5029, "Only one shutdown at a time is possible via mgm server" },
- {5060, "Operation not allowed in single user mode." },
- {5061, "DB is not in single user mode." },
- {5062, "The specified node is not an API node." },
- {5063,
- "Cannot enter single user mode. DB nodes in inconsistent startlevel."},
+ {MgmtSrvr::NODE_SHUTDOWN_IN_PROGESS, "Node shutdown in progress" },
+ {MgmtSrvr::SYSTEM_SHUTDOWN_IN_PROGRESS, "System shutdown in progress" },
+ {MgmtSrvr::NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH,
+ "Node shutdown would cause system crash" },
+ {MgmtSrvr::UNSUPPORTED_NODE_SHUTDOWN,
+ "Unsupported multi node shutdown. Abort option required." },
+ {MgmtSrvr::NODE_NOT_API_NODE, "The specified node is not an API node." },
+ {MgmtSrvr::OPERATION_NOT_ALLOWED_START_STOP,
+ "Operation not allowed while nodes are starting or stopping."},
{MgmtSrvr::NO_CONTACT_WITH_DB_NODES, "No contact with database nodes" }
};
@@ -312,13 +312,16 @@ int MgmtSrvr::translateStopRef(Uint32 errCode)
{
switch(errCode){
case StopRef::NodeShutdownInProgress:
- return 5026;
+ return NODE_SHUTDOWN_IN_PROGESS;
break;
case StopRef::SystemShutdownInProgress:
- return 5027;
+ return SYSTEM_SHUTDOWN_IN_PROGRESS;
break;
case StopRef::NodeShutdownWouldCauseSystemCrash:
- return 5028;
+ return NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH;
+ break;
+ case StopRef::UnsupportedNodeShutdown:
+ return UNSUPPORTED_NODE_SHUTDOWN;
break;
}
return 4999;
@@ -339,42 +342,41 @@ 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)
+MgmtSrvr::getPort() const
+{
+ if(NdbMutex_Lock(m_configMutex))
return 0;
- if(ndb_mgm_find(iter, CFG_NODE_ID, getOwnNodeId()) != 0){
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ if(iter.find(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);
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
unsigned type;
- if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0 ||
+ if(iter.get(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);
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
Uint32 port = 0;
- if(ndb_mgm_get_int_parameter(iter, CFG_MGM_PORT, &port) != 0){
+ if(iter.get(CFG_MGM_PORT, &port) != 0){
ndbout << "Could not find PortNumber in the configuration file." << endl;
- ndb_mgm_destroy_iterator(iter);
+ NdbMutex_Unlock(m_configMutex);
return 0;
}
- ndb_mgm_destroy_iterator(iter);
-
+ NdbMutex_Unlock(m_configMutex);
+
return port;
}
@@ -395,7 +397,9 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
_ownReference(0),
theSignalIdleList(NULL),
theWaitState(WAIT_SUBSCRIBE_CONF),
- m_event_listner(this)
+ m_local_mgm_handle(0),
+ m_event_listner(this),
+ m_master_node(0)
{
DBUG_ENTER("MgmtSrvr::MgmtSrvr");
@@ -413,8 +417,6 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
m_newConfig = NULL;
if (config_filename)
m_configFilename.assign(config_filename);
- else
- m_configFilename.assign("config.ini");
m_nextConfigGenerationNumber = 0;
@@ -449,7 +451,7 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
_config= readConfig();
if (_config == 0) {
ndbout << "Unable to read config file" << endl;
- require(false);
+ exit(-1);
}
}
@@ -467,14 +469,14 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
{
ndb_mgm_configuration_iterator
- *iter = ndb_mgm_create_configuration_iterator(_config->m_configValues,
- CFG_SECTION_NODE);
- for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ for(iter.first(); iter.valid(); iter.next()){
unsigned type, id;
- if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0)
+ if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0)
continue;
- if(ndb_mgm_get_int_parameter(iter, CFG_NODE_ID, &id) != 0)
+ if(iter.get(CFG_NODE_ID, &id) != 0)
continue;
MGM_REQUIRE(id < MAX_NODES);
@@ -497,7 +499,6 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
break;
}
}
- ndb_mgm_destroy_iterator(iter);
}
_props = NULL;
@@ -512,9 +513,10 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
if (_ownNodeId == 0) // we did not get node id from other server
{
NodeId tmp= m_config_retriever->get_configuration_nodeid();
+ int error_code;
if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
- 0, 0, error_string)){
+ 0, 0, error_code, error_string)){
ndbout << "Unable to obtain requested nodeid: "
<< error_string.c_str() << endl;
require(false);
@@ -566,6 +568,8 @@ MgmtSrvr::check_start()
bool
MgmtSrvr::start(BaseString &error_string)
{
+ int mgm_connect_result;
+
DBUG_ENTER("MgmtSrvr::start");
if (_props == NULL) {
if (!check_start()) {
@@ -573,7 +577,8 @@ MgmtSrvr::start(BaseString &error_string)
DBUG_RETURN(false);
}
}
- theFacade= TransporterFacade::theFacadeInstance= new TransporterFacade();
+ theFacade= TransporterFacade::theFacadeInstance
+ = new TransporterFacade();
if(theFacade == 0) {
DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
@@ -601,7 +606,33 @@ MgmtSrvr::start(BaseString &error_string)
theFacade = 0;
DBUG_RETURN(false);
}
-
+
+ if((mgm_connect_result= connect_to_self()) < 0)
+ {
+ ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)",
+ mgm_connect_result);
+ ndbout_c("This is probably a bug.");
+ }
+
+ TransporterRegistry *reg = theFacade->get_registry();
+ for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) {
+ BaseString msg;
+ DBUG_PRINT("info",("Setting dynamic port %d->%d : %d",
+ reg->get_localNodeId(),
+ reg->m_transporter_interface[i].m_remote_nodeId,
+ reg->m_transporter_interface[i].m_s_service_port
+ )
+ );
+ int res = setConnectionDbParameter((int)reg->get_localNodeId(),
+ (int)reg->m_transporter_interface[i]
+ .m_remote_nodeId,
+ (int)CFG_CONNECTION_SERVER_PORT,
+ reg->m_transporter_interface[i]
+ .m_s_service_port,
+ msg);
+ DBUG_PRINT("info",("Set result: %d: %s",res,msg.c_str()));
+ }
+
_ownReference = numberToRef(_blockNumber, _ownNodeId);
startEventLog();
@@ -659,23 +690,16 @@ MgmtSrvr::~MgmtSrvr()
int MgmtSrvr::okToSendTo(NodeId nodeId, bool unCond)
{
- if(nodeId == 0)
- return 0;
-
- if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB)
+ if(nodeId == 0 || getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB)
return WRONG_PROCESS_TYPE;
-
// Check if we have contact with it
if(unCond){
if(theFacade->theClusterMgr->getNodeInfo(nodeId).connected)
return 0;
- return NO_CONTACT_WITH_PROCESS;
}
- if (theFacade->get_node_alive(nodeId) == 0) {
- return NO_CONTACT_WITH_PROCESS;
- } else {
+ else if (theFacade->get_node_alive(nodeId) == true)
return 0;
- }
+ return NO_CONTACT_WITH_PROCESS;
}
void report_unknown_signal(SimpleSignal *signal)
@@ -840,20 +864,108 @@ MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address)
return 0;
}
+int MgmtSrvr::sendStopMgmd(NodeId nodeId,
+ bool abort,
+ bool stop,
+ bool restart,
+ bool nostart,
+ bool initialStart)
+{
+ const char* hostname;
+ Uint32 port;
+ BaseString connect_string;
+
+ {
+ Guard g(m_configMutex);
+ {
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ if(iter.first()) return SEND_OR_RECEIVE_FAILED;
+ if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
+ if(iter.get(CFG_NODE_HOST, &hostname)) return SEND_OR_RECEIVE_FAILED;
+ }
+ {
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
+
+ if(iter.first()) return SEND_OR_RECEIVE_FAILED;
+ if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
+ if(iter.get(CFG_MGM_PORT, &port)) return SEND_OR_RECEIVE_FAILED;
+ }
+ if( strlen(hostname) == 0 )
+ return SEND_OR_RECEIVE_FAILED;
+ }
+ connect_string.assfmt("%s:%u",hostname,port);
+
+ DBUG_PRINT("info",("connect string: %s",connect_string.c_str()));
+
+ NdbMgmHandle h= ndb_mgm_create_handle();
+ if ( h && connect_string.length() > 0 )
+ {
+ ndb_mgm_set_connectstring(h,connect_string.c_str());
+ if(ndb_mgm_connect(h,1,0,0))
+ {
+ DBUG_PRINT("info",("failed ndb_mgm_connect"));
+ return SEND_OR_RECEIVE_FAILED;
+ }
+ if(!restart)
+ {
+ if(ndb_mgm_stop(h, 1, (const int*)&nodeId) < 0)
+ {
+ return SEND_OR_RECEIVE_FAILED;
+ }
+ }
+ else
+ {
+ int nodes[1];
+ nodes[0]= (int)nodeId;
+ if(ndb_mgm_restart2(h, 1, nodes, initialStart, nostart, abort) < 0)
+ {
+ return SEND_OR_RECEIVE_FAILED;
+ }
+ }
+ }
+ ndb_mgm_destroy_handle(&h);
+
+ return 0;
+}
+
/*
* Common method for handeling all STOP_REQ signalling that
* is used by Stopping, Restarting and Single user commands
+ *
+ * In the event that we need to stop a mgmd, we create a mgm
+ * client connection to that mgmd and stop it that way.
+ * This allows us to stop mgm servers when there isn't any real
+ * distributed communication up.
+ *
+ * node_ids.size()==0 means to stop all DB nodes.
+ * MGM nodes will *NOT* be stopped.
+ *
+ * If we work out we should be stopping or restarting ourselves,
+ * we return <0 in stopSelf for restart, >0 for stop
+ * and 0 for do nothing.
*/
-int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
+int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
NodeBitmask &stoppedNodes,
Uint32 singleUserNodeId,
bool abort,
bool stop,
bool restart,
bool nostart,
- bool initialStart)
+ bool initialStart,
+ int* stopSelf)
{
+ int error = 0;
+ DBUG_ENTER("MgmtSrvr::sendSTOP_REQ");
+ DBUG_PRINT("enter", ("no of nodes: %d singleUseNodeId: %d "
+ "abort: %d stop: %d restart: %d "
+ "nostart: %d initialStart: %d",
+ node_ids.size(), singleUserNodeId,
+ abort, stop, restart, nostart, initialStart));
+
stoppedNodes.clear();
SignalSender ss(theFacade);
@@ -890,20 +1002,54 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
// send the signals
NodeBitmask nodes;
- if (nodeId)
+ NodeId nodeId= 0;
+ int use_master_node= 0;
+ int do_send= 0;
+ *stopSelf= 0;
+ NdbNodeBitmask nodes_to_stop;
{
+ for (unsigned i= 0; i < node_ids.size(); i++)
{
- int r;
- if((r = okToSendTo(nodeId, true)) != 0)
- return r;
+ nodeId= node_ids[i];
+ ndbout << "asked to stop " << nodeId << endl;
+ if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
+ nodes_to_stop.set(nodeId);
+ else if (nodeId != getOwnNodeId())
+ {
+ error= sendStopMgmd(nodeId, abort, stop, restart,
+ nostart, initialStart);
+ if (error == 0)
+ stoppedNodes.set(nodeId);
+ }
+ else
+ {
+ ndbout << "which is me" << endl;
+ *stopSelf= (restart)? -1 : 1;
+ stoppedNodes.set(nodeId);
+ }
}
+ }
+ int no_of_nodes_to_stop= nodes_to_stop.count();
+ if (node_ids.size())
+ {
+ if (no_of_nodes_to_stop)
{
- if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
- return SEND_OR_RECEIVE_FAILED;
+ do_send= 1;
+ if (no_of_nodes_to_stop == 1)
+ {
+ nodeId= nodes_to_stop.find(0);
+ }
+ else // multi node stop, send to master
+ {
+ use_master_node= 1;
+ nodes_to_stop.copyto(NdbNodeBitmask::Size, stopReq->nodes);
+ StopReq::setStopNodes(stopReq->requestInfo, 1);
+ }
}
- nodes.set(nodeId);
}
else
+ {
+ nodeId= 0;
while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
{
if(okToSendTo(nodeId, true) == 0)
@@ -913,11 +1059,33 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
nodes.set(nodeId);
}
}
+ }
// now wait for the replies
- int error = 0;
- while (!nodes.isclear())
+ while (!nodes.isclear() || do_send)
{
+ if (do_send)
+ {
+ int r;
+ assert(nodes.count() == 0);
+ if (use_master_node)
+ nodeId= m_master_node;
+ if ((r= okToSendTo(nodeId, true)) != 0)
+ {
+ bool next;
+ if (!use_master_node)
+ DBUG_RETURN(r);
+ m_master_node= nodeId= 0;
+ while((next= getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
+ (r= okToSendTo(nodeId, true)) != 0);
+ if (!next)
+ DBUG_RETURN(NO_CONTACT_WITH_DB_NODES);
+ }
+ if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
+ DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
+ nodes.set(nodeId);
+ do_send= 0;
+ }
SimpleSignal *signal = ss.waitFor();
int gsn = signal->readSignalNumber();
switch (gsn) {
@@ -929,6 +1097,13 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
#endif
assert(nodes.get(nodeId));
nodes.clear(nodeId);
+ if (ref->errorCode == StopRef::MultiNodeShutdownNotMaster)
+ {
+ assert(use_master_node);
+ m_master_node= ref->masterNodeId;
+ do_send= 1;
+ continue;
+ }
error = translateStopRef(ref->errorCode);
break;
}
@@ -939,40 +1114,32 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
ndbout_c("Node %d single user mode", nodeId);
#endif
assert(nodes.get(nodeId));
- assert(singleUserNodeId != 0);
+ if (singleUserNodeId != 0)
+ {
+ stoppedNodes.set(nodeId);
+ }
+ else
+ {
+ assert(no_of_nodes_to_stop > 1);
+ stoppedNodes.bitOR(nodes_to_stop);
+ }
nodes.clear(nodeId);
- stoppedNodes.set(nodeId);
break;
}
case GSN_NF_COMPLETEREP:{
const NFCompleteRep * const rep =
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
#ifdef VM_TRACE
- ndbout_c("Node %d fail completed", rep->failedNodeId);
+ ndbout_c("sendSTOP_REQ Node %d fail completed", rep->failedNodeId);
#endif
+ nodes.clear(rep->failedNodeId); // clear the failed node
+ if (singleUserNodeId == 0)
+ stoppedNodes.set(rep->failedNodeId);
break;
}
case GSN_NODE_FAILREP:{
const NodeFailRep * const rep =
CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
- NodeBitmask failedNodes;
- failedNodes.assign(NodeBitmask::Size, rep->theNodes);
-#ifdef VM_TRACE
- {
- ndbout << "Failed nodes:";
- for (unsigned i = 0; i < 32*NodeBitmask::Size; i++)
- if(failedNodes.get(i))
- ndbout << " " << i;
- ndbout << endl;
- }
-#endif
- failedNodes.bitAND(nodes);
- if (!failedNodes.isclear())
- {
- nodes.bitANDC(failedNodes); // clear the failed nodes
- if (singleUserNodeId == 0)
- stoppedNodes.bitOR(failedNodes);
- }
break;
}
default:
@@ -980,44 +1147,92 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
#ifdef VM_TRACE
ndbout_c("Unknown signal %d", gsn);
#endif
- return SEND_OR_RECEIVE_FAILED;
+ DBUG_RETURN(SEND_OR_RECEIVE_FAILED);
}
}
- return error;
+ if (error && *stopSelf)
+ {
+ *stopSelf= 0;
+ }
+ DBUG_RETURN(error);
}
/*
- * Stop one node
+ * Stop one nodes
*/
-int MgmtSrvr::stopNode(int nodeId, bool abort)
+int MgmtSrvr::stopNodes(const Vector<NodeId> &node_ids,
+ int *stopCount, bool abort, int* stopSelf)
{
+ if (!abort)
+ {
+ NodeId nodeId = 0;
+ ClusterMgr::Node node;
+ while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
+ {
+ node = theFacade->theClusterMgr->getNodeInfo(nodeId);
+ if((node.m_state.startLevel != NodeState::SL_STARTED) &&
+ (node.m_state.startLevel != NodeState::SL_NOTHING))
+ return OPERATION_NOT_ALLOWED_START_STOP;
+ }
+ }
NodeBitmask nodes;
- return sendSTOP_REQ(nodeId,
- nodes,
- 0,
- abort,
- false,
- false,
- false,
- false);
+ int ret= sendSTOP_REQ(node_ids,
+ nodes,
+ 0,
+ abort,
+ false,
+ false,
+ false,
+ false,
+ stopSelf);
+ if (stopCount)
+ *stopCount= nodes.count();
+ return ret;
+}
+
+int MgmtSrvr::shutdownMGM(int *stopCount, bool abort, int *stopSelf)
+{
+ NodeId nodeId = 0;
+ int error;
+
+ while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM))
+ {
+ if(nodeId==getOwnNodeId())
+ continue;
+ error= sendStopMgmd(nodeId, abort, true, false,
+ false, false);
+ if (error == 0)
+ *stopCount++;
+ }
+
+ *stopSelf= 1;
+ *stopCount++;
+
+ return 0;
}
/*
- * Perform system shutdown
+ * Perform DB nodes shutdown.
+ * MGM servers are left in their current state
*/
-int MgmtSrvr::stop(int * stopCount, bool abort)
+int MgmtSrvr::shutdownDB(int * stopCount, bool abort)
{
NodeBitmask nodes;
- int ret = sendSTOP_REQ(0,
+ Vector<NodeId> node_ids;
+
+ int tmp;
+
+ int ret = sendSTOP_REQ(node_ids,
nodes,
0,
abort,
true,
false,
false,
- false);
+ false,
+ &tmp);
if (stopCount)
*stopCount = nodes.count();
return ret;
@@ -1030,7 +1245,7 @@ int MgmtSrvr::stop(int * stopCount, bool abort)
int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
{
if (getNodeType(singleUserNodeId) != NDB_MGM_NODE_TYPE_API)
- return 5062;
+ return NODE_NOT_API_NODE;
NodeId nodeId = 0;
ClusterMgr::Node node;
while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
@@ -1038,17 +1253,20 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
node = theFacade->theClusterMgr->getNodeInfo(nodeId);
if((node.m_state.startLevel != NodeState::SL_STARTED) &&
(node.m_state.startLevel != NodeState::SL_NOTHING))
- return 5063;
+ return OPERATION_NOT_ALLOWED_START_STOP;
}
NodeBitmask nodes;
- int ret = sendSTOP_REQ(0,
+ Vector<NodeId> node_ids;
+ int stopSelf;
+ int ret = sendSTOP_REQ(node_ids,
nodes,
singleUserNodeId,
false,
false,
false,
false,
- false);
+ false,
+ &stopSelf);
if (stopCount)
*stopCount = nodes.count();
return ret;
@@ -1058,36 +1276,82 @@ int MgmtSrvr::enterSingleUser(int * stopCount, Uint32 singleUserNodeId)
* Perform node restart
*/
-int MgmtSrvr::restartNode(int nodeId, bool nostart, bool initialStart,
- bool abort)
+int MgmtSrvr::restartNodes(const Vector<NodeId> &node_ids,
+ int * stopCount, bool nostart,
+ bool initialStart, bool abort,
+ int *stopSelf)
{
NodeBitmask nodes;
- return sendSTOP_REQ(nodeId,
- nodes,
- 0,
- abort,
- false,
- true,
- nostart,
- initialStart);
+ int ret= sendSTOP_REQ(node_ids,
+ nodes,
+ 0,
+ abort,
+ false,
+ true,
+ true,
+ initialStart,
+ stopSelf);
+
+ if (ret)
+ return ret;
+
+ if (stopCount)
+ *stopCount = nodes.count();
+
+ // start up the nodes again
+ int waitTime = 12000;
+ NDB_TICKS maxTime = NdbTick_CurrentMillisecond() + waitTime;
+ for (unsigned i = 0; i < node_ids.size(); i++)
+ {
+ NodeId nodeId= node_ids[i];
+ enum ndb_mgm_node_status s;
+ s = NDB_MGM_NODE_STATUS_NO_CONTACT;
+#ifdef VM_TRACE
+ ndbout_c("Waiting for %d not started", nodeId);
+#endif
+ while (s != NDB_MGM_NODE_STATUS_NOT_STARTED && waitTime > 0)
+ {
+ Uint32 startPhase = 0, version = 0, dynamicId = 0, nodeGroup = 0;
+ Uint32 connectCount = 0;
+ bool system;
+ const char *address;
+ status(nodeId, &s, &version, &startPhase,
+ &system, &dynamicId, &nodeGroup, &connectCount, &address);
+ NdbSleep_MilliSleep(100);
+ waitTime = (maxTime - NdbTick_CurrentMillisecond());
+ }
+ }
+
+ if (nostart)
+ return 0;
+
+ for (unsigned i = 0; i < node_ids.size(); i++)
+ {
+ int result = start(node_ids[i]);
+ }
+ return 0;
}
/*
- * Perform system restart
+ * Perform restart of all DB nodes
*/
-int MgmtSrvr::restart(bool nostart, bool initialStart,
- bool abort, int * stopCount )
+int MgmtSrvr::restartDB(bool nostart, bool initialStart,
+ bool abort, int * stopCount)
{
NodeBitmask nodes;
- int ret = sendSTOP_REQ(0,
+ Vector<NodeId> node_ids;
+ int tmp;
+
+ int ret = sendSTOP_REQ(node_ids,
nodes,
0,
abort,
true,
true,
true,
- initialStart);
+ initialStart,
+ &tmp);
if (ret)
return ret;
@@ -1590,8 +1854,6 @@ void
MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
{
// The way of handling a received signal is taken from the Ndb class.
- int returnCode;
-
int gsn = signal->readSignalNumber();
switch (gsn) {
@@ -1600,8 +1862,13 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
case GSN_EVENT_SUBSCRIBE_REF:
break;
case GSN_EVENT_REP:
- eventReport(refToNode(signal->theSendersBlockRef), signal->getDataPtr());
+ {
+ EventReport *rep = (EventReport*) signal->getDataPtr();
+ if (rep->getNodeId() == 0)
+ rep->setNodeId(refToNode(signal->theSendersBlockRef));
+ eventReport(signal->getDataPtr());
break;
+ }
case GSN_NF_COMPLETEREP:
break;
@@ -1626,19 +1893,22 @@ MgmtSrvr::handleStatus(NodeId nodeId, bool alive, bool nfComplete)
{
DBUG_ENTER("MgmtSrvr::handleStatus");
Uint32 theData[25];
+ EventReport *rep = (EventReport *)theData;
+
theData[1] = nodeId;
if (alive) {
m_started_nodes.push_back(nodeId);
- theData[0] = EventReport::Connected;
+ rep->setEventType(NDB_LE_Connected);
} else {
- theData[0] = EventReport::Disconnected;
+ rep->setEventType(NDB_LE_Connected);
if(nfComplete)
{
DBUG_VOID_RETURN;
}
}
- eventReport(_ownNodeId, theData);
+ rep->setNodeId(_ownNodeId);
+ eventReport(theData);
DBUG_VOID_RETURN;
}
@@ -1703,10 +1973,7 @@ MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const
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);
- }
+ connected_nodes.bitOR(node.m_state.m_connected_nodes);
}
}
}
@@ -1717,7 +1984,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
enum ndb_mgm_node_type type,
struct sockaddr *client_addr,
SOCKET_SIZE_TYPE *client_addr_len,
- BaseString &error_string)
+ int &error_code, BaseString &error_string,
+ int log_event)
{
DBUG_ENTER("MgmtSrvr::alloc_node_id");
DBUG_PRINT("enter", ("nodeid=%d, type=%d, client_addr=%d",
@@ -1726,6 +1994,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
if (*nodeId == 0) {
error_string.appfmt("no-nodeid-checks set in management server.\n"
"node id must be set explicitly in connectstring");
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
DBUG_RETURN(true);
@@ -1748,8 +2017,15 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
int r_config_addr= -1;
unsigned type_c= 0;
+ if(NdbMutex_Lock(m_configMutex))
+ {
+ // should not happen
+ error_string.appfmt("unable to lock configuration mutex");
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ DBUG_RETURN(false);
+ }
ndb_mgm_configuration_iterator
- iter(*(ndb_mgm_configuration *)_config->m_configValues, CFG_SECTION_NODE);
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
for(iter.first(); iter.valid(); iter.next()) {
unsigned tmp= 0;
if(iter.get(CFG_NODE_ID, &tmp)) require(false);
@@ -1816,6 +2092,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"Suggest specifying node id in connectstring,\n"
"or specifying unique host names in config file.",
id_found, tmp);
+ NdbMutex_Unlock(m_configMutex);
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
if (config_hostname == 0) {
@@ -1824,10 +2102,12 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"or specifying unique host names in config file,\n"
"or specifying just one mgmt server in config file.",
tmp);
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
id_found= tmp; // mgmt server matched, check for more matches
}
+ NdbMutex_Unlock(m_configMutex);
if (id_found)
{
@@ -1852,10 +2132,21 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
m_connect_address[id_found].s_addr= 0;
}
m_reserved_nodes.set(id_found);
+ if (theFacade && id_found != theFacade->ownId())
+ {
+ /**
+ * Make sure we're ready to accept connections from this node
+ */
+ theFacade->lock_mutex();
+ theFacade->doConnect(id_found);
+ theFacade->unlock_mutex();
+ }
+
char tmp_str[128];
m_reserved_nodes.getText(tmp_str);
- g_eventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, m_reserved_nodes %s.",
- id_found, get_connect_address(id_found), tmp_str);
+ g_eventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, "
+ "m_reserved_nodes %s.",
+ id_found, get_connect_address(id_found), tmp_str);
DBUG_RETURN(true);
}
@@ -1875,26 +2166,48 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
type_c_string.assfmt("%s(%s)", alias, str);
}
- if (*nodeId == 0) {
+ if (*nodeId == 0)
+ {
if (found_matching_id)
+ {
if (found_matching_type)
+ {
if (found_free_node)
+ {
error_string.appfmt("Connection done from wrong host ip %s.",
(client_addr)?
- inet_ntoa(((struct sockaddr_in *)
+ inet_ntoa(((struct sockaddr_in *)
(client_addr))->sin_addr):"");
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ }
else
+ {
error_string.appfmt("No free node id found for %s.",
type_string.c_str());
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ }
+ }
else
+ {
error_string.appfmt("No %s node defined in config file.",
type_string.c_str());
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ }
else
+ {
error_string.append("No nodes defined in config file.");
- } else {
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ }
+ else
+ {
if (found_matching_id)
+ {
if (found_matching_type)
- if (found_free_node) {
+ {
+ if (found_free_node)
+ {
// have to split these into two since inet_ntoa overwrites itself
error_string.appfmt("Connection with id %d done from wrong host ip %s,",
*nodeId, inet_ntoa(((struct sockaddr_in *)
@@ -1902,27 +2215,44 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
error_string.appfmt(" expected %s(%s).", config_hostname,
r_config_addr ?
"lookup failed" : inet_ntoa(config_addr));
- } else
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ else
+ {
error_string.appfmt("Id %d already allocated by another node.",
*nodeId);
+ error_code = NDB_MGM_ALLOCID_ERROR;
+ }
+ }
else
+ {
error_string.appfmt("Id %d configured as %s, connect attempted as %s.",
*nodeId, type_c_string.c_str(),
type_string.c_str());
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
+ }
else
+ {
error_string.appfmt("No node defined with id=%d in config file.",
*nodeId);
+ error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
+ }
}
- g_eventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s. "
- "Returned error string \"%s\"",
- *nodeId,
- client_addr != 0 ? inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr) : "<none>",
- error_string.c_str());
-
- NodeBitmask connected_nodes2;
- get_connected_nodes(connected_nodes2);
+ if (log_event || error_code == NDB_MGM_ALLOCID_CONFIG_MISMATCH)
{
+ g_eventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s."
+ " Returned error string \"%s\"",
+ *nodeId,
+ client_addr != 0
+ ? inet_ntoa(((struct sockaddr_in *)
+ (client_addr))->sin_addr)
+ : "<none>",
+ error_string.c_str());
+
+ NodeBitmask connected_nodes2;
+ get_connected_nodes(connected_nodes2);
BaseString tmp_connected, tmp_not_connected;
for(Uint32 i = 0; i < MAX_NODES; i++)
{
@@ -1966,11 +2296,12 @@ MgmtSrvr::getNextNodeId(NodeId * nodeId, enum ndb_mgm_node_type type) const
#include "Services.hpp"
void
-MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData)
+MgmtSrvr::eventReport(const Uint32 * theData)
{
const EventReport * const eventReport = (EventReport *)&theData[0];
- EventReport::EventType type = eventReport->getEventType();
+ NodeId nodeId = eventReport->getNodeId();
+ Ndb_logevent_type type = eventReport->getEventType();
// Log event
g_eventLogger.log(type, theData, nodeId,
&m_event_listner[0].m_logLevel);
@@ -1987,12 +2318,16 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
SignalSender ss(theFacade);
ss.lock(); // lock will be released on exit
- bool next;
- NodeId nodeId = 0;
- while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
- theFacade->get_node_alive(nodeId) == false);
-
- if(!next) return NO_CONTACT_WITH_DB_NODES;
+ NodeId nodeId = m_master_node;
+ if (okToSendTo(nodeId, false) != 0)
+ {
+ bool next;
+ nodeId = m_master_node = 0;
+ while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
+ okToSendTo(nodeId, false) != 0);
+ if(!next)
+ return NO_CONTACT_WITH_DB_NODES;
+ }
SimpleSignal ssig;
BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
@@ -2045,14 +2380,20 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
event.Event = BackupEvent::BackupCompleted;
event.Completed.BackupId = rep->backupId;
- event.Completed.NoOfBytes = rep->noOfBytes;
+ event.Completed.NoOfBytes = rep->noOfBytesLow;
event.Completed.NoOfLogBytes = rep->noOfLogBytes;
- event.Completed.NoOfRecords = rep->noOfRecords;
+ event.Completed.NoOfRecords = rep->noOfRecordsLow;
event.Completed.NoOfLogRecords = rep->noOfLogRecords;
event.Completed.stopGCP = rep->stopGCP;
event.Completed.startGCP = rep->startGCP;
event.Nodes = rep->nodes;
+ if (signal->header.theLength >= BackupCompleteRep::SignalLength)
+ {
+ event.Completed.NoOfBytes += ((Uint64)rep->noOfBytesHigh) << 32;
+ event.Completed.NoOfRecords += ((Uint64)rep->noOfRecordsHigh) << 32;
+ }
+
backupId = rep->backupId;
return 0;
}
@@ -2060,7 +2401,7 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
const BackupRef * const ref =
CAST_CONSTPTR(BackupRef, signal->getDataPtr());
if(ref->errorCode == BackupRef::IAmNotMaster){
- nodeId = refToNode(ref->masterRef);
+ m_master_node = nodeId = refToNode(ref->masterRef);
#ifdef VM_TRACE
ndbout_c("I'm not master resending to %d", nodeId);
#endif
@@ -2156,6 +2497,8 @@ MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted)
MgmtSrvr::Allocated_resources::Allocated_resources(MgmtSrvr &m)
: m_mgmsrv(m)
{
+ m_reserved_nodes.clear();
+ m_alloc_timeout= 0;
}
MgmtSrvr::Allocated_resources::~Allocated_resources()
@@ -2174,9 +2517,22 @@ MgmtSrvr::Allocated_resources::~Allocated_resources()
}
void
-MgmtSrvr::Allocated_resources::reserve_node(NodeId id)
+MgmtSrvr::Allocated_resources::reserve_node(NodeId id, NDB_TICKS timeout)
{
m_reserved_nodes.set(id);
+ m_alloc_timeout= NdbTick_CurrentMillisecond() + timeout;
+}
+
+bool
+MgmtSrvr::Allocated_resources::is_timed_out(NDB_TICKS tick)
+{
+ if (m_alloc_timeout && tick > m_alloc_timeout)
+ {
+ g_eventLogger.info("Mgmt server state: nodeid %d timed out.",
+ get_nodeid());
+ return true;
+ }
+ return false;
}
NodeId
@@ -2193,13 +2549,18 @@ MgmtSrvr::Allocated_resources::get_nodeid() const
int
MgmtSrvr::setDbParameter(int node, int param, const char * value,
BaseString& msg){
+
+ if(NdbMutex_Lock(m_configMutex))
+ return -1;
+
/**
* Check parameter
*/
- ndb_mgm_configuration_iterator iter(* _config->m_configValues,
- CFG_SECTION_NODE);
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_NODE);
if(iter.first() != 0){
msg.assign("Unable to find node section (iter.first())");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
@@ -2207,16 +2568,19 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
if(node != 0){
if(iter.find(CFG_NODE_ID, node) != 0){
msg.assign("Unable to find node (iter.find())");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
+ NdbMutex_Unlock(m_configMutex);
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))");
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
if(type == NODE_TYPE_DB)
@@ -2227,6 +2591,7 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
if(type != NODE_TYPE_DB){
msg.assfmt("Invalid node type or no such node (%d %d)",
type, NODE_TYPE_DB);
+ NdbMutex_Unlock(m_configMutex);
return -1;
}
@@ -2252,6 +2617,7 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
break;
}
msg.assign("Could not get parameter");
+ NdbMutex_Unlock(m_configMutex);
return -1;
} while(0);
@@ -2289,9 +2655,158 @@ MgmtSrvr::setDbParameter(int node, int param, const char * value,
} while(node == 0 && iter.next() == 0);
msg.assign("Success");
+ NdbMutex_Unlock(m_configMutex);
+ return 0;
+}
+int
+MgmtSrvr::setConnectionDbParameter(int node1,
+ int node2,
+ int param,
+ int value,
+ BaseString& msg){
+ Uint32 current_value,new_value;
+
+ DBUG_ENTER("MgmtSrvr::setConnectionDbParameter");
+
+ if(NdbMutex_Lock(m_configMutex))
+ {
+ DBUG_RETURN(-1);
+ }
+
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
+
+ if(iter.first() != 0){
+ msg.assign("Unable to find connection section (iter.first())");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ for(;iter.valid();iter.next()) {
+ Uint32 n1,n2;
+ iter.get(CFG_CONNECTION_NODE_1, &n1);
+ iter.get(CFG_CONNECTION_NODE_2, &n2);
+ if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
+ || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
+ break;
+ }
+ if(!iter.valid()) {
+ msg.assign("Unable to find connection between nodes");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-2);
+ }
+
+ if(iter.get(param, &current_value) != 0) {
+ msg.assign("Unable to get current value of parameter");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-3);
+ }
+
+ ConfigValues::Iterator i2(_config->m_configValues->m_config,
+ iter.m_config);
+
+ if(i2.set(param, (unsigned)value) == false) {
+ msg.assign("Unable to set new value of parameter");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-4);
+ }
+
+ if(iter.get(param, &new_value) != 0) {
+ msg.assign("Unable to get parameter after setting it.");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-5);
+ }
+
+ msg.assfmt("%u -> %u",current_value,new_value);
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(1);
+}
+
+
+int
+MgmtSrvr::getConnectionDbParameter(int node1,
+ int node2,
+ int param,
+ int *value,
+ BaseString& msg){
+ DBUG_ENTER("MgmtSrvr::getConnectionDbParameter");
+
+ if(NdbMutex_Lock(m_configMutex))
+ {
+ DBUG_RETURN(-1);
+ }
+
+ ndb_mgm_configuration_iterator
+ iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
+
+ if(iter.first() != 0){
+ msg.assign("Unable to find connection section (iter.first())");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ for(;iter.valid();iter.next()) {
+ Uint32 n1=0,n2=0;
+ iter.get(CFG_CONNECTION_NODE_1, &n1);
+ iter.get(CFG_CONNECTION_NODE_2, &n2);
+ if((n1 == (unsigned)node1 && n2 == (unsigned)node2)
+ || (n1 == (unsigned)node2 && n2 == (unsigned)node1))
+ break;
+ }
+ if(!iter.valid()) {
+ msg.assign("Unable to find connection between nodes");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ if(iter.get(param, (Uint32*)value) != 0) {
+ msg.assign("Unable to get current value of parameter");
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(-1);
+ }
+
+ msg.assfmt("%d",*value);
+ NdbMutex_Unlock(m_configMutex);
+ DBUG_RETURN(1);
+}
+
+void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd)
+{
+ if (theFacade->get_registry()->connect_server(sockfd))
+ {
+ /**
+ * Force an update_connections() so that the
+ * ClusterMgr and TransporterFacade is up to date
+ * with the new connection.
+ * Important for correct node id reservation handling
+ */
+ NdbMutex_Lock(theFacade->theMutexPtr);
+ theFacade->get_registry()->update_connections();
+ NdbMutex_Unlock(theFacade->theMutexPtr);
+ }
+}
+
+int MgmtSrvr::connect_to_self(void)
+{
+ int r= 0;
+ m_local_mgm_handle= ndb_mgm_create_handle();
+ snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string),
+ "localhost:%u",getPort());
+ ndb_mgm_set_connectstring(m_local_mgm_handle, m_local_mgm_connect_string);
+
+ if((r= ndb_mgm_connect(m_local_mgm_handle, 0, 0, 0)) < 0)
+ {
+ ndb_mgm_destroy_handle(&m_local_mgm_handle);
+ return r;
+ }
+ // TransporterRegistry now owns this NdbMgmHandle and will destroy it.
+ theFacade->get_registry()->set_mgm_handle(m_local_mgm_handle);
+
return 0;
}
+
+
template class MutexVector<unsigned short>;
template class MutexVector<Ndb_mgmd_event_service::Event_listener>;
template class MutexVector<EventSubscribeReq>;
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index 2a64bf5dbf5..187f225470a 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -51,6 +51,7 @@ class Ndb_mgmd_event_service : public EventLoggerBase
public:
struct Event_listener : public EventLoggerBase {
NDB_SOCKET_TYPE m_socket;
+ Uint32 m_parsable;
};
private:
@@ -105,7 +106,8 @@ public:
~Allocated_resources();
// methods to reserve/allocate resources which
// will be freed when running destructor
- void reserve_node(NodeId id);
+ void reserve_node(NodeId id, NDB_TICKS timeout);
+ bool is_timed_out(NDB_TICKS tick);
bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId); }
bool is_reserved(NodeBitmask mask) { return !mask.bitAND(m_reserved_nodes).isclear(); }
bool isclear() { return m_reserved_nodes.isclear(); }
@@ -113,6 +115,7 @@ public:
private:
MgmtSrvr &m_mgmsrv;
NodeBitmask m_reserved_nodes;
+ NDB_TICKS m_alloc_timeout;
};
NdbMutex *m_node_id_mutex;
@@ -173,10 +176,13 @@ public:
STATIC_CONST( NODE_SHUTDOWN_IN_PROGESS = 5026 );
STATIC_CONST( SYSTEM_SHUTDOWN_IN_PROGRESS = 5027 );
STATIC_CONST( NODE_SHUTDOWN_WOULD_CAUSE_SYSTEM_CRASH = 5028 );
- STATIC_CONST( NO_CONTACT_WITH_CLUSTER = 6666 );
- STATIC_CONST( OPERATION_IN_PROGRESS = 6667 );
-
+
STATIC_CONST( NO_CONTACT_WITH_DB_NODES = 5030 );
+ STATIC_CONST( UNSUPPORTED_NODE_SHUTDOWN = 5031 );
+
+ STATIC_CONST( NODE_NOT_API_NODE = 5062 );
+ STATIC_CONST( OPERATION_NOT_ALLOWED_START_STOP = 5063 );
+
/**
* This enum specifies the different signal loggig modes possible to set
* with the setSignalLoggingMode method.
@@ -249,12 +255,15 @@ public:
* @param processId: Id of the DB process to stop
* @return 0 if succeeded, otherwise: as stated above, plus:
*/
- int stopNode(int nodeId, bool abort = false);
+ int stopNodes(const Vector<NodeId> &node_ids, int *stopCount, bool abort,
+ int *stopSelf);
+
+ int shutdownMGM(int *stopCount, bool abort, int *stopSelf);
/**
- * Stop the system
+ * shutdown the DB nodes
*/
- int stop(int * cnt = 0, bool abort = false);
+ int shutdownDB(int * cnt = 0, bool abort = false);
/**
* print version info about a node
@@ -283,18 +292,19 @@ public:
int start(int processId);
/**
- * Restart a node
+ * Restart nodes
* @param processId: Id of the DB process to start
*/
- int restartNode(int processId, bool nostart, bool initialStart,
- bool abort = false);
+ int restartNodes(const Vector<NodeId> &node_ids,
+ int *stopCount, bool nostart,
+ bool initialStart, bool abort, int *stopSelf);
/**
- * Restart the system
+ * Restart all DB nodes
*/
- int restart(bool nostart, bool initialStart,
- bool abort = false,
- int * stopCount = 0);
+ int restartDB(bool nostart, bool initialStart,
+ bool abort = false,
+ int * stopCount = 0);
struct BackupEvent {
enum Event {
@@ -313,9 +323,9 @@ public:
Uint32 ErrorCode;
} FailedToStart ;
struct {
+ Uint64 NoOfBytes;
+ Uint64 NoOfRecords;
Uint32 BackupId;
- Uint32 NoOfBytes;
- Uint32 NoOfRecords;
Uint32 NoOfLogBytes;
Uint32 NoOfLogRecords;
Uint32 startGCP;
@@ -427,8 +437,10 @@ public:
*/
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,
- BaseString &error_string);
+ struct sockaddr *client_addr,
+ SOCKET_SIZE_TYPE *client_addr_len,
+ int &error_code, BaseString &error_string,
+ int log_event = 1);
/**
*
@@ -463,7 +475,17 @@ public:
int getPort() const;
int setDbParameter(int node, int parameter, const char * value, BaseString&);
-
+ int setConnectionDbParameter(int node1, int node2, int param, int value,
+ BaseString& msg);
+ int getConnectionDbParameter(int node1, int node2, int param,
+ int *value, BaseString& msg);
+
+ int connect_to_self(void);
+
+ void transporter_connect(NDB_SOCKET_TYPE sockfd);
+
+ ConfigRetriever *get_config_retriever() { return m_config_retriever; };
+
const char *get_connect_address(Uint32 node_id);
void get_connected_nodes(NodeBitmask &connected_nodes) const;
SocketServer *get_socket_server() { return m_socket_server; }
@@ -472,14 +494,22 @@ public:
private:
//**************************************************************************
- int sendSTOP_REQ(NodeId nodeId,
+ int sendStopMgmd(NodeId nodeId,
+ bool abort,
+ bool stop,
+ bool restart,
+ bool nostart,
+ bool initialStart);
+
+ int sendSTOP_REQ(const Vector<NodeId> &node_ids,
NodeBitmask &stoppedNodes,
Uint32 singleUserNodeId,
bool abort,
bool stop,
bool restart,
bool nostart,
- bool initialStart);
+ bool initialStart,
+ int *stopSelf);
/**
* Check if it is possible to send a signal to a (DB) process
@@ -592,7 +622,7 @@ private:
/**
* An event from <i>nodeId</i> has arrived
*/
- void eventReport(NodeId nodeId, const Uint32 * theData);
+ void eventReport(const Uint32 * theData);
//**************************************************************************
@@ -614,6 +644,8 @@ private:
// signal arrives.
// We wait in receiveOptimisedResponse and signal in handleReceivedSignal.
+ NdbMgmHandle m_local_mgm_handle;
+ char m_local_mgm_connect_string[20];
class TransporterFacade * theFacade;
int sendVersionReq( int processId, Uint32 &version, const char **address);
@@ -629,6 +661,8 @@ private:
friend class Ndb_mgmd_event_service;
Ndb_mgmd_event_service m_event_listner;
+ NodeId m_master_node;
+
/**
* Handles the thread wich upon a 'Node is started' event will
* set the node's previous loglevel settings.
diff --git a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
index 60740e5e105..e56643a3d7e 100644
--- a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
@@ -52,7 +52,15 @@ Config *
MgmtSrvr::readConfig() {
Config *conf;
InitConfigFileParser parser;
- conf = parser.parseConfig(m_configFilename.c_str());
+ if (m_configFilename.length())
+ {
+ conf = parser.parseConfig(m_configFilename.c_str());
+ }
+ else
+ {
+ ndbout_c("Reading cluster configuration using my.cnf");
+ conf = parser.parse_mycnf();
+ }
return conf;
}
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 715522cae2a..0524aba4c32 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -25,14 +25,18 @@
#include <signaldata/SetLogLevelOrd.hpp>
#include <LogLevel.hpp>
#include <BaseString.hpp>
-#include <Base64.hpp>
#include <ConfigValues.hpp>
#include <mgmapi_configuration.hpp>
#include <Vector.hpp>
#include "Services.hpp"
+#include "../mgmapi/ndb_logevent.hpp"
+
+#include <base64.h>
extern bool g_StopServer;
+extern bool g_RestartServer;
+extern EventLogger g_eventLogger;
static const unsigned int MAX_READ_TIMEOUT = 1000 ;
static const unsigned int MAX_WRITE_TIMEOUT = 100 ;
@@ -133,6 +137,9 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("password", String, Mandatory, "Password"),
MGM_ARG("public key", String, Mandatory, "Public key"),
MGM_ARG("endian", String, Optional, "Endianness"),
+ MGM_ARG("name", String, Optional, "Name of connection"),
+ MGM_ARG("timeout", Int, Optional, "Timeout in seconds"),
+ MGM_ARG("log_event", Int, Optional, "Log failure in cluster log"),
MGM_CMD("get version", &MgmApiSession::getVersion, ""),
@@ -140,7 +147,13 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
- MGM_CMD("restart node", &MgmApiSession::restart, ""),
+ MGM_CMD("restart node", &MgmApiSession::restart_v1, ""),
+ MGM_ARG("node", String, Mandatory, "Nodes to restart"),
+ MGM_ARG("initialstart", Int, Optional, "Initial start"),
+ MGM_ARG("nostart", Int, Optional, "No start"),
+ MGM_ARG("abort", Int, Optional, "Abort"),
+
+ MGM_CMD("restart node v2", &MgmApiSession::restart_v2, ""),
MGM_ARG("node", String, Mandatory, "Nodes to restart"),
MGM_ARG("initialstart", Int, Optional, "Initial start"),
MGM_ARG("nostart", Int, Optional, "No start"),
@@ -181,19 +194,18 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("abort backup", &MgmApiSession::abortBackup, ""),
MGM_ARG("id", Int, Mandatory, "Backup id"),
- /**
- * Global Replication
- */
- MGM_CMD("rep", &MgmApiSession::repCommand, ""),
- MGM_ARG("request", Int, Mandatory, "Command"),
+ MGM_CMD("stop", &MgmApiSession::stop_v1, ""),
+ MGM_ARG("node", String, Mandatory, "Node"),
+ MGM_ARG("abort", Int, Mandatory, "Node"),
- MGM_CMD("stop", &MgmApiSession::stop, ""),
+ MGM_CMD("stop v2", &MgmApiSession::stop_v2, ""),
MGM_ARG("node", String, Mandatory, "Node"),
MGM_ARG("abort", Int, Mandatory, "Node"),
MGM_CMD("stop all", &MgmApiSession::stopAll, ""),
MGM_ARG("abort", Int, Mandatory, "Node"),
-
+ MGM_ARG("stop", String, Optional, "MGM/DB or both"),
+
MGM_CMD("enter single user", &MgmApiSession::enterSingleUser, ""),
MGM_ARG("nodeId", Int, Mandatory, "Node"),
@@ -207,6 +219,8 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("bye", &MgmApiSession::bye, ""),
+ MGM_CMD("end session", &MgmApiSession::endSession, ""),
+
MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""),
MGM_ARG("node", Int, Mandatory, "Node"),
MGM_ARG("category", Int, Mandatory, "Event category"),
@@ -226,17 +240,48 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("parameter", String, Mandatory, "Parameter"),
MGM_ARG("value", String, Mandatory, "Value"),
+ MGM_CMD("set connection parameter",
+ &MgmApiSession::setConnectionParameter, ""),
+ MGM_ARG("node1", String, Mandatory, "Node1 ID"),
+ MGM_ARG("node2", String, Mandatory, "Node2 ID"),
+ MGM_ARG("param", String, Mandatory, "Parameter"),
+ MGM_ARG("value", String, Mandatory, "Value"),
+
+ MGM_CMD("get connection parameter",
+ &MgmApiSession::getConnectionParameter, ""),
+ MGM_ARG("node1", String, Mandatory, "Node1 ID"),
+ MGM_ARG("node2", String, Mandatory, "Node2 ID"),
+ MGM_ARG("param", String, Mandatory, "Parameter"),
+
MGM_CMD("listen event", &MgmApiSession::listen_event, ""),
MGM_ARG("node", Int, Optional, "Node"),
+ MGM_ARG("parsable", Int, Optional, "Parsable"),
MGM_ARG("filter", String, Mandatory, "Event category"),
MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""),
MGM_CMD("check connection", &MgmApiSession::check_connection, ""),
+ MGM_CMD("transporter connect", &MgmApiSession::transporter_connect, ""),
+
+ MGM_CMD("get mgmd nodeid", &MgmApiSession::get_mgmd_nodeid, ""),
+
+ MGM_CMD("report event", &MgmApiSession::report_event, ""),
+ MGM_ARG("length", Int, Mandatory, "Length"),
+ MGM_ARG("data", String, Mandatory, "Data"),
+
MGM_END()
};
+struct PurgeStruct
+{
+ NodeBitmask free_nodes;/* free nodes as reported
+ * by ndbd in apiRegReqConf
+ */
+ BaseString *str;
+ NDB_TICKS tick;
+};
+
MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock)
: SocketServer::Session(sock), m_mgmsrv(mgm)
{
@@ -245,6 +290,7 @@ MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE 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);
+ m_stopSelf= 0;
DBUG_VOID_RETURN;
}
@@ -264,6 +310,10 @@ MgmApiSession::~MgmApiSession()
NDB_CLOSE_SOCKET(m_socket);
m_socket= NDB_INVALID_SOCKET;
}
+ if(m_stopSelf < 0)
+ g_RestartServer= true;
+ if(m_stopSelf)
+ g_StopServer= true;
DBUG_VOID_RETURN;
}
@@ -386,11 +436,15 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
{
const char *cmd= "get nodeid reply";
Uint32 version, nodeid= 0, nodetype= 0xff;
+ Uint32 timeout= 20; // default seconds timeout
const char * transporter;
const char * user;
const char * password;
const char * public_key;
const char * endian= NULL;
+ const char * name= NULL;
+ Uint32 log_event= 1;
+ bool log_event_version;
union { long l; char c[sizeof(long)]; } endian_check;
args.get("version", &version);
@@ -401,6 +455,10 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
args.get("password", &password);
args.get("public key", &public_key);
args.get("endian", &endian);
+ args.get("name", &name);
+ args.get("timeout", &timeout);
+ /* for backwards compatability keep track if client uses new protocol */
+ log_event_version= args.get("log_event", &log_event);
endian_check.l = 1;
if(endian
@@ -440,14 +498,39 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
NodeId tmp= nodeid;
if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){
BaseString error_string;
- if (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype,
- (struct sockaddr*)&addr, &addrlen, error_string)){
+ int error_code;
+ NDB_TICKS tick= 0;
+ /* only report error on second attempt as not to clog the cluster log */
+ while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype,
+ (struct sockaddr*)&addr, &addrlen, error_code, error_string,
+ tick == 0 ? 0 : log_event))
+ {
+ /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */
+ if (tick == 0 && error_code != NDB_MGM_ALLOCID_CONFIG_MISMATCH)
+ {
+ // attempt to free any timed out reservations
+ tick= NdbTick_CurrentMillisecond();
+ struct PurgeStruct ps;
+ m_mgmsrv.get_connected_nodes(ps.free_nodes);
+ // invert connected_nodes to get free nodes
+ ps.free_nodes.bitXORC(NodeBitmask());
+ ps.str= 0;
+ ps.tick= tick;
+ m_mgmsrv.get_socket_server()->
+ foreachSession(stop_session_if_timed_out,&ps);
+ m_mgmsrv.get_socket_server()->checkSessions();
+ error_string = "";
+ continue;
+ }
const char *alias;
const char *str;
alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)
nodetype, &str);
m_output->println(cmd);
m_output->println("result: %s", error_string.c_str());
+ /* only use error_code protocol if client knows about it */
+ if (log_event_version)
+ m_output->println("error_code: %d", error_code);
m_output->println("");
return;
}
@@ -467,8 +550,11 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
m_output->println("nodeid: %u", tmp);
m_output->println("result: Ok");
m_output->println("");
- m_allocated_resources->reserve_node(tmp);
+ m_allocated_resources->reserve_node(tmp, timeout*1000);
+ if (name)
+ g_eventLogger.info("Node %d: %s", tmp, name);
+
return;
}
@@ -556,23 +642,26 @@ MgmApiSession::getConfig_common(Parser_t::Context &,
}
}
+ NdbMutex_Lock(m_mgmsrv.m_configMutex);
const ConfigValues * cfg = &conf->m_configValues->m_config;
const Uint32 size = cfg->getPackedSize();
UtilBuffer src;
cfg->pack(src);
+ NdbMutex_Unlock(m_mgmsrv.m_configMutex);
- BaseString str;
- int res = base64_encode(src, str);
+ char *tmp_str = (char *) malloc(base64_needed_encoded_length(src.length()));
+ int res = base64_encode(src.get_data(), src.length(), tmp_str);
m_output->println("get config reply");
m_output->println("result: Ok");
- m_output->println("Content-Length: %d", str.length());
+ m_output->println("Content-Length: %d", strlen(tmp_str));
m_output->println("Content-Type: ndbconfig/octet-stream");
m_output->println("Content-Transfer-Encoding: base64");
m_output->println("");
- m_output->println(str.c_str());
+ m_output->println(tmp_str);
+ free(tmp_str);
return;
}
@@ -651,7 +740,8 @@ MgmApiSession::startBackup(Parser<MgmApiSession>::Context &,
}
else{
m_output->println("result: Ok");
- m_output->println("id: %d", backupId);
+ if (completed)
+ m_output->println("id: %d", backupId);
}
m_output->println("");
DBUG_VOID_RETURN;
@@ -674,30 +764,6 @@ MgmApiSession::abortBackup(Parser<MgmApiSession>::Context &,
m_output->println("");
}
-/*****************************************************************************
- * Global Replication
- *****************************************************************************/
-
-void
-MgmApiSession::repCommand(Parser<MgmApiSession>::Context &,
- Properties const &args) {
-
- Uint32 request = 0;
- args.get("request", &request);
-
- Uint32 repReqId;
- int result = m_mgmsrv.repCommand(&repReqId, request, true);
-
- m_output->println("global replication reply");
- if(result != 0)
- m_output->println("result: %s", get_error_text(result));
- else{
- m_output->println("result: Ok");
- m_output->println("id: %d", repReqId);
- }
- m_output->println("");
-}
-
/*****************************************************************************/
void
@@ -721,11 +787,22 @@ MgmApiSession::dumpState(Parser<MgmApiSession>::Context &,
void
MgmApiSession::bye(Parser<MgmApiSession>::Context &,
- Properties const &) {
+ Properties const &) {
m_stop = true;
}
void
+MgmApiSession::endSession(Parser<MgmApiSession>::Context &,
+ Properties const &) {
+ if(m_allocated_resources)
+ delete m_allocated_resources;
+
+ m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
+
+ m_output->println("end session reply");
+}
+
+void
MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
Properties const &args) {
const char *reply= "set cluster loglevel reply";
@@ -825,8 +902,19 @@ MgmApiSession::stopSignalLog(Parser<MgmApiSession>::Context &,
}
void
-MgmApiSession::restart(Parser<MgmApiSession>::Context &,
+MgmApiSession::restart_v1(Parser<MgmApiSession>::Context &,
Properties const &args) {
+ restart(args,1);
+}
+
+void
+MgmApiSession::restart_v2(Parser<MgmApiSession>::Context &,
+ Properties const &args) {
+ restart(args,2);
+}
+
+void
+MgmApiSession::restart(Properties const &args, int version) {
Uint32
nostart = 0,
initialstart = 0,
@@ -847,14 +935,12 @@ MgmApiSession::restart(Parser<MgmApiSession>::Context &,
}
int restarted = 0;
- int result = 0;
-
- for(size_t i = 0; i < nodes.size(); i++)
- if((result = m_mgmsrv.restartNode(nodes[i],
- nostart != 0,
- initialstart != 0,
- abort != 0)) == 0)
- restarted++;
+ int result= m_mgmsrv.restartNodes(nodes,
+ &restarted,
+ nostart != 0,
+ initialstart != 0,
+ abort != 0,
+ &m_stopSelf);
m_output->println("restart reply");
if(result != 0){
@@ -862,6 +948,8 @@ MgmApiSession::restart(Parser<MgmApiSession>::Context &,
} else
m_output->println("result: Ok");
m_output->println("restarted: %d", restarted);
+ if(version>1)
+ m_output->println("disconnect: %d", (m_stopSelf)?1:0);
m_output->println("");
}
@@ -878,7 +966,7 @@ MgmApiSession::restartAll(Parser<MgmApiSession>::Context &,
args.get("nostart", &nostart);
int count = 0;
- int result = m_mgmsrv.restart(nostart, initialstart, abort, &count);
+ int result = m_mgmsrv.restartDB(nostart, initialstart, abort, &count);
m_output->println("restart reply");
if(result != 0)
@@ -971,15 +1059,31 @@ MgmApiSession::getInfoClusterLog(Parser<MgmApiSession>::Context &,
}
void
-MgmApiSession::stop(Parser<MgmApiSession>::Context &,
- Properties const &args) {
+MgmApiSession::stop_v1(Parser<MgmApiSession>::Context &,
+ Properties const &args) {
+ stop(args,1);
+}
+
+void
+MgmApiSession::stop_v2(Parser<MgmApiSession>::Context &,
+ Properties const &args) {
+ stop(args,2);
+}
+
+void
+MgmApiSession::stop(Properties const &args, int version) {
Uint32 abort;
char *nodes_str;
Vector<NodeId> nodes;
args.get("node", (const char **)&nodes_str);
if(nodes_str == NULL)
+ {
+ m_output->println("stop reply");
+ m_output->println("result: empty node list");
+ m_output->println("");
return;
+ }
args.get("abort", &abort);
char *p, *last;
@@ -989,29 +1093,10 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
nodes.push_back(atoi(p));
}
- int stop_self= 0;
- size_t i;
-
- for(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(i=0; i < nodes.size(); i++)
- if (nodes[i] != m_mgmsrv.getOwnNodeId()) {
- if((result = m_mgmsrv.stopNode(nodes[i], abort != 0)) == 0)
- stopped++;
- } else
- stopped++;
+ int stopped= 0;
+ int result= 0;
+ if (nodes.size())
+ result= m_mgmsrv.stopNodes(nodes, &stopped, abort != 0, &m_stopSelf);
m_output->println("stop reply");
if(result != 0)
@@ -1019,28 +1104,41 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
else
m_output->println("result: Ok");
m_output->println("stopped: %d", stopped);
+ if(version>1)
+ m_output->println("disconnect: %d", (m_stopSelf)?1:0);
m_output->println("");
-
- if (stop_self)
- g_StopServer= true;
}
-
void
MgmApiSession::stopAll(Parser<MgmApiSession>::Context &,
- Properties const &args) {
- int stopped = 0;
+ Properties const &args) {
+ int stopped[2] = {0,0};
Uint32 abort;
args.get("abort", &abort);
- int result = m_mgmsrv.stop(&stopped, abort != 0);
+ BaseString stop;
+ const char* tostop= "db";
+ int ver=1;
+ if (args.get("stop", stop))
+ {
+ tostop= stop.c_str();
+ ver= 2;
+ }
+
+ int result= 0;
+ if(strstr(tostop,"db"))
+ result= m_mgmsrv.shutdownDB(&stopped[0], abort != 0);
+ if(!result && strstr(tostop,"mgm"))
+ result= m_mgmsrv.shutdownMGM(&stopped[1], abort!=0, &m_stopSelf);
m_output->println("stop reply");
if(result != 0)
m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
- m_output->println("stopped: %d", stopped);
+ m_output->println("stopped: %d", stopped[0]+stopped[1]);
+ if(ver >1)
+ m_output->println("disconnect: %d", (m_stopSelf)?1:0);
m_output->println("");
}
@@ -1173,13 +1271,13 @@ MgmApiSession::startAll(Parser<MgmApiSession>::Context &,
void
MgmApiSession::setLogFilter(Parser_t::Context &ctx,
const class Properties &args) {
- Uint32 level;
+ Uint32 severity;
Uint32 enable;
- args.get("level", &level);
+ args.get("level", &severity);
args.get("enable", &enable);
- int result = m_mgmsrv.setEventLogFilter(level, enable);
+ int result = m_mgmsrv.setEventLogFilter(severity, enable);
m_output->println("set logfilter reply");
m_output->println("result: %d", result);
@@ -1202,28 +1300,52 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId)
Uint32 threshold;
LogLevel::EventCategory cat;
Logger::LoggerLevel severity;
+ EventLoggerBase::EventTextFunction textF;
int i, n;
DBUG_ENTER("Ndb_mgmd_event_service::log");
DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
- if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity))
+ if (EventLoggerBase::event_lookup(eventType,cat,threshold,severity,textF))
DBUG_VOID_RETURN;
char m_text[256];
- EventLogger::getText(m_text, sizeof(m_text), eventType, theData, nodeId);
+ EventLogger::getText(m_text, sizeof(m_text),
+ textF, theData, nodeId);
+
+ BaseString str("log event reply\n");
+ str.appfmt("type=%d\n", eventType);
+ str.appfmt("time=%d\n", 0);
+ str.appfmt("source_nodeid=%d\n", nodeId);
+ for (i= 0; ndb_logevent_body[i].token; i++)
+ {
+ if ( ndb_logevent_body[i].type != eventType)
+ continue;
+ int val= theData[ndb_logevent_body[i].index];
+ if (ndb_logevent_body[i].index_fn)
+ val= (*(ndb_logevent_body[i].index_fn))(val);
+ str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val);
+ }
- Vector<NDB_SOCKET_TYPE> copy;
+ Vector<NDB_SOCKET_TYPE> copy;
m_clients.lock();
for(i = m_clients.size() - 1; i >= 0; i--)
{
if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat))
{
- int fd= m_clients[i].m_socket;
- if(fd != NDB_INVALID_SOCKET &&
- println_socket(fd, MAX_WRITE_TIMEOUT, m_text) == -1)
+ NDB_SOCKET_TYPE fd= m_clients[i].m_socket;
+ if(fd != NDB_INVALID_SOCKET)
{
- copy.push_back(fd);
- m_clients.erase(i, false);
+ int r;
+ if (m_clients[i].m_parsable)
+ r= println_socket(fd,
+ MAX_WRITE_TIMEOUT, str.c_str());
+ else
+ r= println_socket(fd,
+ MAX_WRITE_TIMEOUT, m_text);
+ if (r == -1) {
+ copy.push_back(fd);
+ m_clients.erase(i, false);
+ }
}
}
}
@@ -1344,17 +1466,64 @@ MgmApiSession::setParameter(Parser_t::Context &,
}
void
+MgmApiSession::setConnectionParameter(Parser_t::Context &ctx,
+ Properties const &args) {
+ BaseString node1, node2, param, value;
+ args.get("node1", node1);
+ args.get("node2", node2);
+ args.get("param", param);
+ args.get("value", value);
+
+ BaseString result;
+ int ret = m_mgmsrv.setConnectionDbParameter(atoi(node1.c_str()),
+ atoi(node2.c_str()),
+ atoi(param.c_str()),
+ atoi(value.c_str()),
+ result);
+
+ m_output->println("set connection parameter reply");
+ m_output->println("message: %s", result.c_str());
+ m_output->println("result: %s", (ret>0)?"Ok":"Failed");
+ m_output->println("");
+}
+
+void
+MgmApiSession::getConnectionParameter(Parser_t::Context &ctx,
+ Properties const &args) {
+ BaseString node1, node2, param;
+ int value = 0;
+
+ args.get("node1", node1);
+ args.get("node2", node2);
+ args.get("param", param);
+
+ BaseString result;
+ int ret = m_mgmsrv.getConnectionDbParameter(atoi(node1.c_str()),
+ atoi(node2.c_str()),
+ atoi(param.c_str()),
+ &value,
+ result);
+
+ m_output->println("get connection parameter reply");
+ m_output->println("value: %d", value);
+ m_output->println("result: %s", (ret>0)?"Ok":result.c_str());
+ m_output->println("");
+}
+
+void
MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx,
Properties const & args) {
-
+ Uint32 parsable= 0;
BaseString node, param, value;
args.get("node", node);
args.get("filter", param);
+ args.get("parsable", &parsable);
int result = 0;
BaseString msg;
Ndb_mgmd_event_service::Event_listener le;
+ le.m_parsable = parsable;
le.m_socket = m_socket;
Vector<BaseString> list;
@@ -1412,14 +1581,6 @@ done:
m_output->println("");
}
-struct PurgeStruct
-{
- NodeBitmask free_nodes;/* free nodes as reported
- * by ndbd in apiRegReqConf
- */
- BaseString *str;
-};
-
void
MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data)
{
@@ -1427,7 +1588,20 @@ MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *da
struct PurgeStruct &ps= *(struct PurgeStruct *)data;
if (s->m_allocated_resources->is_reserved(ps.free_nodes))
{
- ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
+ if (ps.str)
+ ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
+ s->stopSession();
+ }
+}
+
+void
+MgmApiSession::stop_session_if_timed_out(SocketServer::Session *_s, void *data)
+{
+ MgmApiSession *s= (MgmApiSession *)_s;
+ struct PurgeStruct &ps= *(struct PurgeStruct *)data;
+ if (s->m_allocated_resources->is_reserved(ps.free_nodes) &&
+ s->m_allocated_resources->is_timed_out(ps.tick))
+ {
s->stopSession();
}
}
@@ -1444,6 +1618,7 @@ MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx,
ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes
m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps);
+ m_mgmsrv.get_socket_server()->checkSessions();
m_output->println("purge stale sessions reply");
if (str.length() > 0)
@@ -1461,6 +1636,50 @@ MgmApiSession::check_connection(Parser_t::Context &ctx,
m_output->println("");
}
+void
+MgmApiSession::transporter_connect(Parser_t::Context &ctx,
+ Properties const &args)
+{
+ m_mgmsrv.transporter_connect(m_socket);
+
+ m_stop= true;
+ m_stopped= true; // force a stop (no closing socket)
+ m_socket= NDB_INVALID_SOCKET; // so nobody closes it
+}
+
+void
+MgmApiSession::get_mgmd_nodeid(Parser_t::Context &ctx,
+ Properties const &args)
+{
+ m_output->println("get mgmd nodeid reply");
+ m_output->println("nodeid:%u",m_mgmsrv.getOwnNodeId());
+ m_output->println("");
+}
+
+void
+MgmApiSession::report_event(Parser_t::Context &ctx,
+ Properties const &args)
+{
+ Uint32 length;
+ const char *data_string;
+ Uint32 data[25];
+
+ args.get("length", &length);
+ args.get("data", &data_string);
+
+ BaseString tmp(data_string);
+ Vector<BaseString> item;
+ tmp.split(item, " ");
+ for (int i = 0; i < length ; i++)
+ {
+ sscanf(item[i].c_str(), "%u", data+i);
+ }
+
+ m_mgmsrv.eventReport(data);
+ m_output->println("report event reply");
+ m_output->println("result: ok");
+ 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 f5621a319a6..6e0bb701d7b 100644
--- a/ndb/src/mgmsrv/Services.hpp
+++ b/ndb/src/mgmsrv/Services.hpp
@@ -30,6 +30,7 @@
class MgmApiSession : public SocketServer::Session
{
+ static void stop_session_if_timed_out(SocketServer::Session *_s, void *data);
static void stop_session_if_not_connected(SocketServer::Session *_s, void *data);
private:
typedef Parser<MgmApiSession> Parser_t;
@@ -40,6 +41,7 @@ private:
Parser_t *m_parser;
MgmtSrvr::Allocated_resources *m_allocated_resources;
char m_err_str[1024];
+ int m_stopSelf; // -1 is restart, 0 do nothing, 1 stop
void getConfig_common(Parser_t::Context &ctx,
const class Properties &args,
@@ -62,7 +64,9 @@ public:
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);
- void restart(Parser_t::Context &ctx, const class Properties &args);
+ void restart(const class Properties &args, int version);
+ void restart_v1(Parser_t::Context &ctx, const class Properties &args);
+ void restart_v2(Parser_t::Context &ctx, const class Properties &args);
void restartAll(Parser_t::Context &ctx, const class Properties &args);
void insertError(Parser_t::Context &ctx, const class Properties &args);
void setTrace(Parser_t::Context &ctx, const class Properties &args);
@@ -74,23 +78,35 @@ public:
void abortBackup(Parser_t::Context &ctx, const class Properties &args);
void enterSingleUser(Parser_t::Context &ctx, const class Properties &args);
void exitSingleUser(Parser_t::Context &ctx, const class Properties &args);
- void stop(Parser_t::Context &ctx, const class Properties &args);
+ void stop_v1(Parser_t::Context &ctx, const class Properties &args);
+ void stop_v2(Parser_t::Context &ctx, const class Properties &args);
+ void stop(const class Properties &args, int version);
void stopAll(Parser_t::Context &ctx, const class Properties &args);
void start(Parser_t::Context &ctx, const class Properties &args);
void startAll(Parser_t::Context &ctx, const class Properties &args);
void bye(Parser_t::Context &ctx, const class Properties &args);
+ void endSession(Parser_t::Context &ctx, const class Properties &args);
void setLogLevel(Parser_t::Context &ctx, const class Properties &args);
void setClusterLogLevel(Parser_t::Context &ctx,
const class Properties &args);
void setLogFilter(Parser_t::Context &ctx, const class Properties &args);
void setParameter(Parser_t::Context &ctx, const class Properties &args);
+ void setConnectionParameter(Parser_t::Context &ctx,
+ const class Properties &args);
+ void getConnectionParameter(Parser_t::Context &ctx,
+ Properties const &args);
+
void listen_event(Parser_t::Context &ctx, const class Properties &args);
void purge_stale_sessions(Parser_t::Context &ctx, const class Properties &args);
void check_connection(Parser_t::Context &ctx, const class Properties &args);
-
- void repCommand(Parser_t::Context &ctx, const class Properties &args);
+
+ void transporter_connect(Parser_t::Context &ctx, Properties const &args);
+
+ void get_mgmd_nodeid(Parser_t::Context &ctx, Properties const &args);
+
+ void report_event(Parser_t::Context &ctx, Properties const &args);
};
class MgmApiService : public SocketServer::Service {
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index 01845687ce1..5960a3517b5 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -40,7 +40,7 @@
#if defined NDB_OSE || defined NDB_SOFTOSE
#include <efs.h>
#else
-#include "CommandInterpreter.hpp"
+#include <ndb_mgmclient.hpp>
#endif
#undef DEBUG
@@ -48,16 +48,61 @@
const char progname[] = "mgmtsrvr";
+// copied from mysql.cc to get readline
+extern "C" {
+#if defined( __WIN__) || defined(OS2)
+#include <conio.h>
+#elif !defined(__NETWARE__)
+#include <readline/readline.h>
+extern "C" int add_history(const char *command); /* From readline directory */
+#define HAVE_READLINE
+#endif
+}
+
+static int
+read_and_execute(Ndb_mgmclient* com, const char * prompt, int _try_reconnect)
+{
+ static char *line_read = (char *)NULL;
+
+ /* If the buffer has already been allocated, return the memory
+ to the free pool. */
+ if (line_read)
+ {
+ free (line_read);
+ line_read = (char *)NULL;
+ }
+#ifdef HAVE_READLINE
+ /* Get a line from the user. */
+ line_read = readline (prompt);
+ /* If the line has any text in it, save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+#else
+ static char linebuffer[254];
+ fputs(prompt, stdout);
+ linebuffer[sizeof(linebuffer)-1]=0;
+ line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
+ if (line_read == linebuffer) {
+ char *q=linebuffer;
+ while (*q > 31) q++;
+ *q=0;
+ line_read= strdup(linebuffer);
+ }
+#endif
+ return com->execute(line_read,_try_reconnect);
+}
/**
* @struct MgmGlobals
* @brief Global Variables used in the management server
- ******************************************************************************/
+ *****************************************************************************/
+
/** Command line arguments */
static int opt_daemon; // NOT bool, bool need not be int
static int opt_non_interactive;
static int opt_interactive;
static const char * opt_config_filename= 0;
+static int opt_mycnf = 0;
struct MgmGlobals {
MgmGlobals();
@@ -67,7 +112,7 @@ struct MgmGlobals {
NodeId localNodeId;
bool use_specific_ip;
char * interface_name;
- int port;
+ short unsigned int port;
/** The Mgmt Server */
MgmtSrvr * mgmObject;
@@ -87,6 +132,7 @@ static MgmGlobals *glob= 0;
* Global variables
*/
bool g_StopServer;
+bool g_RestartServer;
extern EventLogger g_eventLogger;
extern int global_mgmt_server_check;
@@ -98,13 +144,6 @@ enum ndb_mgmd_options {
};
NDB_STD_OPTS_VARS;
-#if NDB_VERSION_MAJOR <= 4
-#undef OPT_NDB_CONNECTSTRING
-#define OPT_NDB_CONNECTSTRING 1023
-#else
-
-#endif
-
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_mgmd"),
@@ -129,15 +168,13 @@ static struct my_option my_long_options[] =
"Don't run as daemon, but don't read from stdin",
(gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
-#if NDB_VERSION_MAJOR <= 4
- { "config-file", 'c',
- "-c provided for backwards compatability, will be removed in 5.0."
- " Use -f instead",
- (gptr*) &opt_config_filename, (gptr*) &opt_config_filename, 0,
- GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
+ { "mycnf", 256,
+ "Read cluster config from my.cnf",
+ (gptr*) &opt_mycnf, (gptr*) &opt_mycnf, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
+
static void short_usage_sub(void)
{
printf("Usage: %s [OPTIONS]\n", my_progname);
@@ -149,28 +186,28 @@ static void usage()
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- ndb_std_get_one_option(optid, opt, argument ? argument :
- "d:t:O,/tmp/ndb_mgmd.trace");
-#if NDB_VERSION_MAJOR <= 4
- switch (optid) {
- case 'c':
- printf("Warning: -c will be removed in 5.0, use -f instead\n");
- break;
- }
-#endif
- return 0;
-}
/*
* MAIN
*/
int main(int argc, char** argv)
{
+ int mgm_connect_result;
+
NDB_INIT(argv[0]);
+
+ const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+
+ int ho_error;
+#ifndef DBUG_OFF
+ opt_debug= "d:t:O,/tmp/ndb_mgmd.trace";
+#endif
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
+ exit(ho_error);
+
+start:
glob= new MgmGlobals;
/**
@@ -184,26 +221,32 @@ int main(int argc, char** argv)
global_mgmt_server_check = 1;
- const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
- load_defaults("my",load_default_groups,&argc,&argv);
-
- int ho_error;
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
- exit(ho_error);
-
if (opt_interactive ||
opt_non_interactive ||
g_print_full_config) {
opt_daemon= 0;
}
+ if (opt_mycnf && opt_config_filename)
+ {
+ ndbout_c("Both --mycnf and -f is not supported");
+ return 0;
+ }
+
+ if (opt_mycnf == 0 && opt_config_filename == 0)
+ {
+ struct stat buf;
+ if (stat("config.ini", &buf) != -1)
+ opt_config_filename = "config.ini";
+ }
+
glob->socketServer = new SocketServer();
MgmApiService * mapi = new MgmApiService();
glob->mgmObject = new MgmtSrvr(glob->socketServer,
- opt_config_filename,
- opt_connect_str);
+ opt_config_filename,
+ opt_connect_str);
if (g_print_full_config)
goto the_end;
@@ -244,7 +287,8 @@ int main(int argc, char** argv)
glob->interface_name = 0;
}
- if(!glob->socketServer->setup(mapi, glob->port, glob->interface_name)){
+ if(!glob->socketServer->setup(mapi, &glob->port, glob->interface_name))
+ {
ndbout_c("Unable to setup management port: %d!\n"
"Please check if the port is already used,\n"
"(perhaps a ndb_mgmd is already running),\n"
@@ -253,7 +297,7 @@ int main(int argc, char** argv)
delete mapi;
goto error_end;
}
-
+
if(!glob->mgmObject->check_start()){
ndbout_c("Unable to check start management server.");
ndbout_c("Probably caused by illegal initial configuration file.");
@@ -300,25 +344,37 @@ int main(int argc, char** argv)
g_eventLogger.info(msg);
g_StopServer = false;
+ g_RestartServer= false;
glob->socketServer->startServer();
#if ! defined NDB_OSE && ! defined NDB_SOFTOSE
if(opt_interactive) {
- CommandInterpreter com(* glob->mgmObject);
- while(com.readAndExecute());
+ BaseString con_str;
+ if(glob->interface_name)
+ con_str.appfmt("host=%s:%d", glob->interface_name, glob->port);
+ else
+ con_str.appfmt("localhost:%d", glob->port);
+ Ndb_mgmclient com(con_str.c_str(), 1);
+ while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
} else
#endif
- {
- while(g_StopServer != true)
- NdbSleep_MilliSleep(500);
- }
-
- g_eventLogger.info("Shutting down server...");
+ {
+ while(g_StopServer != true)
+ NdbSleep_MilliSleep(500);
+ }
+
+ if(g_RestartServer)
+ g_eventLogger.info("Restarting server...");
+ else
+ g_eventLogger.info("Shutting down server...");
glob->socketServer->stopServer();
+ // We disconnect from the ConfigRetreiver mgmd when we delete glob below
glob->socketServer->stopSessions(true);
g_eventLogger.info("Shutdown complete");
the_end:
delete glob;
+ if(g_RestartServer)
+ goto start;
ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
return 0;
error_end:
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index cd559a544a8..fbff57d3168 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -215,7 +215,7 @@ ClusterMgr::threadMain( ){
* It is now time to send a new Heartbeat
*/
if (theNode.hbCounter >= theNode.hbFrequency) {
- theNode.hbSent++;
+ theNode.m_info.m_heartbeat_cnt++;
theNode.hbCounter = 0;
}
@@ -232,7 +232,7 @@ ClusterMgr::threadMain( ){
theFacade.sendSignalUnCond(&signal, nodeId);
}//if
- if (theNode.hbSent == 4 && theNode.hbFrequency > 0){
+ if (theNode.m_info.m_heartbeat_cnt == 4 && theNode.hbFrequency > 0){
reportNodeFailed(i);
}//if
}
@@ -266,6 +266,7 @@ ClusterMgr::Node::Node()
: m_state(NodeState::SL_NOTHING) {
compatible = nfCompleteRep = true;
connected = defined = m_alive = false;
+ m_state.m_connected_nodes.clear();
}
/******************************************************************************
@@ -337,7 +338,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
node.compatible = ndbCompatible_api_ndb(NDB_VERSION,
node.m_info.m_version);
}
-
+
node.m_state = apiRegConf->nodeState;
if (node.compatible && (node.m_state.startLevel == NodeState::SL_STARTED ||
node.m_state.startLevel == NodeState::SL_SINGLEUSER)){
@@ -345,7 +346,7 @@ ClusterMgr::execAPI_REGCONF(const Uint32 * theData){
} else {
set_node_alive(node, false);
}//if
- node.hbSent = 0;
+ node.m_info.m_heartbeat_cnt = 0;
node.hbCounter = 0;
if (node.m_info.m_type != NodeInfo::REP) {
node.hbFrequency = (apiRegConf->apiHeartbeatFrequency * 10) - 50;
@@ -414,9 +415,15 @@ ClusterMgr::reportConnected(NodeId nodeId){
Node & theNode = theNodes[nodeId];
theNode.connected = true;
- theNode.hbSent = 0;
+ theNode.m_info.m_heartbeat_cnt = 0;
theNode.hbCounter = 0;
-
+
+ /**
+ * make sure the node itself is marked connected even
+ * if first API_REGCONF has not arrived
+ */
+ theNode.m_state.m_connected_nodes.set(nodeId);
+
if (theNode.m_info.m_type != NodeInfo::REP) {
theNode.hbFrequency = 0;
}
@@ -434,7 +441,9 @@ ClusterMgr::reportDisconnected(NodeId nodeId){
noOfConnectedNodes--;
theNodes[nodeId].connected = false;
- theNodes[nodeId].m_info.m_connectCount ++;
+
+ theNodes[nodeId].m_state.m_connected_nodes.clear();
+
reportNodeFailed(nodeId);
}
@@ -444,19 +453,23 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){
Node & theNode = theNodes[nodeId];
set_node_alive(theNode, false);
+ theNode.m_info.m_connectCount ++;
+
if(theNode.connected)
+ {
theFacade.doDisconnect(nodeId);
-
+ }
const bool report = (theNode.m_state.startLevel != NodeState::SL_NOTHING);
theNode.m_state.startLevel = NodeState::SL_NOTHING;
- if(report){
+ if(report)
+ {
theFacade.ReportNodeDead(nodeId);
- }
-
- theNode.nfCompleteRep = false;
+ }
- if(noOfAliveNodes == 0){
+ theNode.nfCompleteRep = false;
+ if(noOfAliveNodes == 0)
+ {
theFacade.m_globalDictCache.lock();
theFacade.m_globalDictCache.invalidate_all();
theFacade.m_globalDictCache.unlock();
diff --git a/ndb/src/ndbapi/ClusterMgr.hpp b/ndb/src/ndbapi/ClusterMgr.hpp
index 3a2005127cd..1a1e622a889 100644
--- a/ndb/src/ndbapi/ClusterMgr.hpp
+++ b/ndb/src/ndbapi/ClusterMgr.hpp
@@ -73,13 +73,13 @@ public:
*/
Uint32 hbFrequency; // Heartbeat frequence
Uint32 hbCounter; // # milliseconds passed since last hb sent
- Uint32 hbSent; // # heartbeats sent (without answer)
};
const Node & getNodeInfo(NodeId) const;
Uint32 getNoOfConnectedNodes() const;
+ void hb_received(NodeId);
+
Uint32 m_connect_count;
-
private:
Uint32 noOfAliveNodes;
Uint32 noOfConnectedNodes;
@@ -129,6 +129,12 @@ ClusterMgr::getNoOfConnectedNodes() const {
return noOfConnectedNodes;
}
+inline
+void
+ClusterMgr::hb_received(NodeId nodeId) {
+ theNodes[nodeId].m_info.m_heartbeat_cnt= 0;
+}
+
/*****************************************************************************/
/**
diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp
index 66ce6266fb9..bb59c16fb7c 100644
--- a/ndb/src/ndbapi/DictCache.cpp
+++ b/ndb/src/ndbapi/DictCache.cpp
@@ -45,6 +45,8 @@ void Ndb_local_table_info::destroy(Ndb_local_table_info *info)
Ndb_local_table_info::Ndb_local_table_info(NdbTableImpl *table_impl)
{
m_table_impl= table_impl;
+ m_first_tuple_id = ~(Uint64)0;
+ m_last_tuple_id = ~(Uint64)0;
}
Ndb_local_table_info::~Ndb_local_table_info()
@@ -83,11 +85,14 @@ LocalDictCache::drop(const char * name){
* Global cache
*/
GlobalDictCache::GlobalDictCache(){
+ DBUG_ENTER("GlobalDictCache::GlobalDictCache");
m_tableHash.createHashTable();
m_waitForTableCondition = NdbCondition_Create();
+ DBUG_VOID_RETURN;
}
GlobalDictCache::~GlobalDictCache(){
+ DBUG_ENTER("GlobalDictCache::~GlobalDictCache");
NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
while(curr != 0){
Vector<TableVersion> * vers = curr->theData;
@@ -97,20 +102,52 @@ GlobalDictCache::~GlobalDictCache(){
delete (* vers)[i].m_impl;
}
delete curr->theData;
+ curr->theData= NULL;
curr = m_tableHash.getNext(curr);
}
-
m_tableHash.releaseHashTable();
NdbCondition_Destroy(m_waitForTableCondition);
+ DBUG_VOID_RETURN;
}
-#include <NdbOut.hpp>
+void GlobalDictCache::printCache()
+{
+ DBUG_ENTER("GlobalDictCache::printCache");
+ NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
+ while(curr != 0){
+ DBUG_PRINT("curr", ("len: %d, hash: %d, lk: %d, str: %s",
+ curr->len, curr->hash, curr->localkey1, curr->str));
+ if (curr->theData){
+ Vector<TableVersion> * vers = curr->theData;
+ const unsigned sz = vers->size();
+ for(unsigned i = 0; i<sz ; i++){
+ TableVersion tv= (*vers)[i];
+ DBUG_PRINT(" ", ("vers[%d]: ver: %d, refCount: %d, status: %d",
+ sz, tv.m_version, tv.m_refCount, tv.m_status));
+ if(tv.m_impl != 0)
+ {
+ DBUG_PRINT(" ", ("m_impl: internalname: %s",
+ tv.m_impl->m_internalName.c_str()));
+ }
+ }
+ }
+ else
+ {
+ DBUG_PRINT(" ", ("NULL"));
+ }
+ curr = m_tableHash.getNext(curr);
+ }
+ DBUG_VOID_RETURN;
+}
-NdbTableImpl *
+NdbTableImpl *
GlobalDictCache::get(const char * name)
{
+ DBUG_ENTER("GlobalDictCache::get");
+ DBUG_PRINT("enter", ("name: %s", name));
+
const Uint32 len = strlen(name);
- Vector<TableVersion> * versions = 0;
+ Vector<TableVersion> * versions = 0;
versions = m_tableHash.getData(name, len);
if(versions == 0){
versions = new Vector<TableVersion>(2);
@@ -125,7 +162,7 @@ GlobalDictCache::get(const char * name)
switch(ver->m_status){
case OK:
ver->m_refCount++;
- return ver->m_impl;
+ DBUG_RETURN(ver->m_impl);
case DROPPED:
retreive = true; // Break loop
break;
@@ -144,24 +181,28 @@ GlobalDictCache::get(const char * name)
tmp.m_status = RETREIVING;
tmp.m_refCount = 1; // The one retreiving it
versions->push_back(tmp);
- return 0;
+ DBUG_RETURN(0);
}
NdbTableImpl *
GlobalDictCache::put(const char * name, NdbTableImpl * tab)
{
+ DBUG_ENTER("GlobalDictCache::put");
+ DBUG_PRINT("enter", ("name: %s, internal_name: %s",
+ name, tab ? tab->m_internalName.c_str() : "tab NULL"));
+
const Uint32 len = strlen(name);
Vector<TableVersion> * vers = m_tableHash.getData(name, len);
if(vers == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
const Uint32 sz = vers->size();
if(sz == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
@@ -176,7 +217,7 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
if(tab == 0)
{
- // No table found in db
+ DBUG_PRINT("info", ("No table found in db"));
vers->erase(sz - 1);
}
else if (ver.m_impl == 0) {
@@ -203,53 +244,59 @@ GlobalDictCache::put(const char * name, NdbTableImpl * tab)
abort();
}
NdbCondition_Broadcast(m_waitForTableCondition);
- return tab;
+ DBUG_RETURN(tab);
}
void
GlobalDictCache::drop(NdbTableImpl * tab)
{
+ DBUG_ENTER("GlobalDictCache::drop");
+ DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
+
unsigned i;
const Uint32 len = strlen(tab->m_internalName.c_str());
Vector<TableVersion> * vers =
m_tableHash.getData(tab->m_internalName.c_str(), len);
if(vers == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
const Uint32 sz = vers->size();
if(sz == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
-
+
for(i = 0; i < sz; i++){
TableVersion & ver = (* vers)[i];
if(ver.m_impl == tab){
- if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
+ if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
ver.m_version != tab->m_version){
- ndbout_c("Dropping with refCount=%d status=%d impl=%p",
- ver.m_refCount, ver.m_status, ver.m_impl);
+ DBUG_PRINT("info", ("Dropping with refCount=%d status=%d impl=%p",
+ ver.m_refCount, ver.m_status, ver.m_impl));
break;
}
-
+ DBUG_PRINT("info", ("Found table to drop, i: %d, name: %s",
+ i, ver.m_impl->m_internalName.c_str()));
ver.m_refCount--;
ver.m_status = DROPPED;
if(ver.m_refCount == 0){
+ DBUG_PRINT("info", ("refCount is zero, deleting m_impl"))
delete ver.m_impl;
vers->erase(i);
}
- return;
+ DBUG_VOID_RETURN;
}
}
-
+
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);
+ DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
+ i, ver.m_version, ver.m_refCount,
+ ver.m_status, ver.m_impl));
}
abort();
@@ -295,21 +342,25 @@ GlobalDictCache::invalidate_all()
}
void
-GlobalDictCache::release(NdbTableImpl * tab){
+GlobalDictCache::release(NdbTableImpl * tab)
+{
+ DBUG_ENTER("GlobalDictCache::release");
+ DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
+
unsigned i;
const Uint32 len = strlen(tab->m_internalName.c_str());
Vector<TableVersion> * vers =
m_tableHash.getData(tab->m_internalName.c_str(), len);
if(vers == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
const Uint32 sz = vers->size();
if(sz == 0){
// Should always tried to retreive it first
- // and then there should be a record
+ // and thus there should be a record
abort();
}
@@ -318,20 +369,21 @@ GlobalDictCache::release(NdbTableImpl * tab){
if(ver.m_impl == tab){
if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
ver.m_version != tab->m_version){
- ndbout_c("Releasing with refCount=%d status=%d impl=%p",
- ver.m_refCount, ver.m_status, ver.m_impl);
+ DBUG_PRINT("info", ("Releasing with refCount=%d status=%d impl=%p",
+ ver.m_refCount, ver.m_status, ver.m_impl));
break;
}
ver.m_refCount--;
- return;
+ DBUG_VOID_RETURN;
}
}
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);
+ DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
+ i, ver.m_version, ver.m_refCount,
+ ver.m_status, ver.m_impl));
}
abort();
diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp
index 52bd57ea217..19198e88824 100644
--- a/ndb/src/ndbapi/DictCache.hpp
+++ b/ndb/src/ndbapi/DictCache.hpp
@@ -33,6 +33,11 @@ public:
static Ndb_local_table_info *create(NdbTableImpl *table_impl, Uint32 sz=0);
static void destroy(Ndb_local_table_info *);
NdbTableImpl *m_table_impl;
+
+ // range of cached tuple ids per thread
+ Uint64 m_first_tuple_id;
+ Uint64 m_last_tuple_id;
+
Uint64 m_local_data[1]; // Must be last member. Used to access extra space.
private:
Ndb_local_table_info(NdbTableImpl *table_impl);
@@ -82,6 +87,8 @@ public:
};
private:
+ void printCache();
+
struct TableVersion {
Uint32 m_version;
Uint32 m_refCount;
diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am
index 1ba80ef7d85..522e78dd6e0 100644
--- a/ndb/src/ndbapi/Makefile.am
+++ b/ndb/src/ndbapi/Makefile.am
@@ -14,19 +14,16 @@ libndbapi_la_SOURCES = \
Ndberr.cpp \
ndberror.c \
NdbErrorOut.cpp \
- NdbConnection.cpp \
- NdbConnectionScan.cpp \
+ NdbTransaction.cpp \
+ NdbTransactionScan.cpp \
NdbOperation.cpp \
NdbOperationSearch.cpp \
NdbOperationScan.cpp \
NdbOperationInt.cpp \
NdbOperationDefine.cpp \
NdbOperationExec.cpp \
- NdbResultSet.cpp \
NdbScanOperation.cpp NdbScanFilter.cpp \
NdbIndexOperation.cpp \
- NdbEventOperation.cpp \
- NdbEventOperationImpl.cpp \
NdbApiSignal.cpp \
NdbRecAttr.cpp \
NdbUtil.cpp \
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index 1ae1030e463..9d1c78a5972 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -27,8 +27,7 @@ Name: Ndb.cpp
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
#include <NdbOperation.hpp>
-#include <NdbConnection.hpp>
-#include <NdbEventOperation.hpp>
+#include <NdbTransaction.hpp>
#include <NdbRecAttr.hpp>
#include <md5_hash.hpp>
#include <NdbSleep.h>
@@ -43,11 +42,13 @@ void connect();
Connect to any node which has no connection at the moment.
****************************************************************************/
-NdbConnection* Ndb::doConnect(Uint32 tConNode)
+NdbTransaction* Ndb::doConnect(Uint32 tConNode)
{
Uint32 tNode;
Uint32 tAnyAlive = 0;
- int TretCode;
+ int TretCode= 0;
+
+ DBUG_ENTER("Ndb::doConnect");
if (tConNode != 0) {
TretCode = NDB_connect(tConNode);
@@ -55,7 +56,7 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
//****************************************************************************
// We have connections now to the desired node. Return
//****************************************************************************
- return getConnectedNdbConnection(tConNode);
+ DBUG_RETURN(getConnectedNdbTransaction(tConNode));
} else if (TretCode != 0) {
tAnyAlive = 1;
}//if
@@ -78,10 +79,13 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
//****************************************************************************
// We have connections now to the desired node. Return
//****************************************************************************
- return getConnectedNdbConnection(tNode);
+ DBUG_RETURN(getConnectedNdbTransaction(tNode));
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
+ DBUG_PRINT("info",("tried node %d, TretCode %d, error code %d, %s",
+ tNode, TretCode, getNdbError().code,
+ getNdbError().message));
}
}
else // just do a regular round robin
@@ -103,10 +107,11 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
//****************************************************************************
// We have connections now to the desired node. Return
//****************************************************************************
- return getConnectedNdbConnection(tNode);
+ DBUG_RETURN(getConnectedNdbTransaction(tNode));
} else if (TretCode != 0) {
tAnyAlive= 1;
}//if
+ DBUG_PRINT("info",("tried node %d TretCode %d", tNode, TretCode));
} while (Tcount < tNoOfDbNodes);
}
//****************************************************************************
@@ -121,7 +126,7 @@ NdbConnection* Ndb::doConnect(Uint32 tConNode)
} else {
theError.code = 4009;
}//if
- return NULL;
+ DBUG_RETURN(NULL);
}
int
@@ -134,36 +139,38 @@ Ndb::NDB_connect(Uint32 tNode)
int tReturnCode;
TransporterFacade *tp = TransporterFacade::instance();
+ DBUG_ENTER("Ndb::NDB_connect");
+
bool nodeAvail = tp->get_node_alive(tNode);
if(nodeAvail == false){
- return 0;
+ DBUG_RETURN(0);
}
- NdbConnection * tConArray = theConnectionArray[tNode];
+ NdbTransaction * tConArray = theConnectionArray[tNode];
if (tConArray != NULL) {
- return 2;
+ DBUG_RETURN(2);
}
- NdbConnection * tNdbCon = getNdbCon(); // Get free connection object.
+ NdbTransaction * tNdbCon = getNdbCon(); // Get free connection object.
if (tNdbCon == NULL) {
- return 4;
+ DBUG_RETURN(4);
}//if
NdbApiSignal* tSignal = getSignal(); // Get signal object
if (tSignal == NULL) {
releaseNdbCon(tNdbCon);
- return 4;
+ DBUG_RETURN(4);
}//if
if (tSignal->setSignal(GSN_TCSEIZEREQ) == -1) {
releaseNdbCon(tNdbCon);
releaseSignal(tSignal);
- return 4;
+ DBUG_RETURN(4);
}//if
tSignal->setData(tNdbCon->ptr2int(), 1);
//************************************************
-// Set connection pointer as NdbConnection object
+// Set connection pointer as NdbTransaction object
//************************************************
tSignal->setData(theMyRef, 2); // Set my block reference
- tNdbCon->Status(NdbConnection::Connecting); // Set status to connecting
+ tNdbCon->Status(NdbTransaction::Connecting); // Set status to connecting
Uint32 nodeSequence;
{ // send and receive signal
Guard guard(tp->theMutexPtr);
@@ -182,34 +189,37 @@ Ndb::NDB_connect(Uint32 tNode)
tReturnCode = -1;
}//if
}
- if ((tReturnCode == 0) && (tNdbCon->Status() == NdbConnection::Connected)) {
+ if ((tReturnCode == 0) && (tNdbCon->Status() == NdbTransaction::Connected)) {
//************************************************
// Send and receive was successful
//************************************************
- NdbConnection* tPrevFirst = theConnectionArray[tNode];
+ NdbTransaction* tPrevFirst = theConnectionArray[tNode];
tNdbCon->setConnectedNodeId(tNode, nodeSequence);
tNdbCon->setMyBlockReference(theMyRef);
theConnectionArray[tNode] = tNdbCon;
tNdbCon->theNext = tPrevFirst;
- return 1;
+ DBUG_RETURN(1);
} else {
releaseNdbCon(tNdbCon);
//****************************************************************************
// Unsuccessful connect is indicated by 3.
//****************************************************************************
- return 3;
+ DBUG_PRINT("info",
+ ("unsuccessful connect tReturnCode %d, tNdbCon->Status() %d",
+ tReturnCode, tNdbCon->Status()));
+ DBUG_RETURN(3);
}//if
}//Ndb::NDB_connect()
-NdbConnection *
-Ndb::getConnectedNdbConnection(Uint32 nodeId){
- NdbConnection* next = theConnectionArray[nodeId];
+NdbTransaction *
+Ndb::getConnectedNdbTransaction(Uint32 nodeId){
+ NdbTransaction* next = theConnectionArray[nodeId];
theConnectionArray[nodeId] = next->theNext;
next->theNext = NULL;
return next;
-}//Ndb::getConnectedNdbConnection()
+}//Ndb::getConnectedNdbTransaction()
/*****************************************************************************
disconnect();
@@ -219,9 +229,10 @@ Remark: Disconnect all connections to the database.
void
Ndb::doDisconnect()
{
- DBUG_ENTER("Ndb::doDisconnect");
- NdbConnection* tNdbCon;
+ NdbTransaction* tNdbCon;
CHECK_STATUS_MACRO_VOID;
+ /* DBUG_ENTER must be after CHECK_STATUS_MACRO_VOID because of 'return' */
+ DBUG_ENTER("Ndb::doDisconnect");
Uint32 tNoOfDbNodes = theImpl->theNoOfDBnodes;
Uint8 *theDBnodes= theImpl->theDBnodes;
@@ -231,14 +242,14 @@ Ndb::doDisconnect()
Uint32 tNode = theDBnodes[i];
tNdbCon = theConnectionArray[tNode];
while (tNdbCon != NULL) {
- NdbConnection* tmpNdbCon = tNdbCon;
+ NdbTransaction* tmpNdbCon = tNdbCon;
tNdbCon = tNdbCon->theNext;
releaseConnectToNdb(tmpNdbCon);
}//while
}//for
tNdbCon = theTransactionList;
while (tNdbCon != NULL) {
- NdbConnection* tmpNdbCon = tNdbCon;
+ NdbTransaction* tmpNdbCon = tNdbCon;
tNdbCon = tNdbCon->theNext;
releaseConnectToNdb(tmpNdbCon);
}//while
@@ -292,34 +303,58 @@ Ndb::waitUntilReady(int timeout)
}
/*****************************************************************************
-NdbConnection* startTransaction();
+NdbTransaction* startTransaction();
Return Value: Returns a pointer to a connection object.
Return NULL otherwise.
Remark: Start transaction. Synchronous.
*****************************************************************************/
-NdbConnection*
-Ndb::startTransaction(Uint32 aPriority, const char * keyData, Uint32 keyLen)
+NdbTransaction*
+Ndb::startTransaction(const NdbDictionary::Table *table,
+ const char * keyData, Uint32 keyLen)
{
DBUG_ENTER("Ndb::startTransaction");
if (theInitState == Initialised) {
theError.code = 0;
checkFailedNode();
- /**
- * If the user supplied key data
- * We will make a qualified quess to which node is the primary for the
- * the fragment and contact that node
- */
+ /**
+ * If the user supplied key data
+ * We will make a qualified quess to which node is the primary for the
+ * the fragment and contact that node
+ */
Uint32 nodeId;
- if(keyData != 0) {
- nodeId = 0; // guess not supported
- // nodeId = m_ndb_cluster_connection->guess_primary_node(keyData, keyLen);
+ NdbTableImpl* impl;
+ if(table != 0 && keyData != 0 && (impl= &NdbTableImpl::getImpl(*table)))
+ {
+ Uint32 hashValue;
+ {
+ Uint32 buf[4];
+ if((UintPtr(keyData) & 7) == 0 && (keyLen & 3) == 0)
+ {
+ md5_hash(buf, (const Uint64*)keyData, keyLen >> 2);
+ }
+ else
+ {
+ Uint64 tmp[1000];
+ tmp[keyLen/8] = 0;
+ memcpy(tmp, keyData, keyLen);
+ md5_hash(buf, tmp, (keyLen+3) >> 2);
+ }
+ hashValue= buf[1];
+ }
+ const Uint16 *nodes;
+ Uint32 cnt= impl->get_nodes(hashValue, &nodes);
+ if(cnt)
+ nodeId= nodes[0];
+ else
+ nodeId= 0;
} else {
nodeId = 0;
}//if
+
{
- NdbConnection *trans= startTransactionLocal(aPriority, nodeId);
+ NdbTransaction *trans= startTransactionLocal(0, nodeId);
DBUG_PRINT("exit",("start trans: 0x%x transid: 0x%llx",
trans, trans ? trans->getTransactionId() : 0));
DBUG_RETURN(trans);
@@ -330,15 +365,15 @@ Ndb::startTransaction(Uint32 aPriority, const char * keyData, Uint32 keyLen)
}//Ndb::startTransaction()
/*****************************************************************************
-NdbConnection* hupp(NdbConnection* pBuddyTrans);
+NdbTransaction* hupp(NdbTransaction* pBuddyTrans);
Return Value: Returns a pointer to a connection object.
Connected to the same node as pBuddyTrans
and also using the same transction id
Remark: Start transaction. Synchronous.
*****************************************************************************/
-NdbConnection*
-Ndb::hupp(NdbConnection* pBuddyTrans)
+NdbTransaction*
+Ndb::hupp(NdbTransaction* pBuddyTrans)
{
DBUG_ENTER("Ndb::hupp");
@@ -354,7 +389,7 @@ Ndb::hupp(NdbConnection* pBuddyTrans)
checkFailedNode();
Uint32 nodeId = pBuddyTrans->getConnectedNodeId();
- NdbConnection* pCon = startTransactionLocal(aPriority, nodeId);
+ NdbTransaction* pCon = startTransactionLocal(aPriority, nodeId);
if(pCon == NULL)
DBUG_RETURN(NULL);
@@ -375,8 +410,7 @@ Ndb::hupp(NdbConnection* pBuddyTrans)
}//if
}//Ndb::hupp()
-
-NdbConnection*
+NdbTransaction*
Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
{
#ifdef VM_TRACE
@@ -390,13 +424,21 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
DBUG_ENTER("Ndb::startTransactionLocal");
DBUG_PRINT("enter", ("nodeid: %d", nodeId));
- NdbConnection* tConnection;
+ if(unlikely(theRemainingStartTransactions == 0))
+ {
+ theError.code = 4006;
+ DBUG_RETURN(0);
+ }
+
+ NdbTransaction* tConnection;
Uint64 tFirstTransId = theFirstTransId;
tConnection = doConnect(nodeId);
if (tConnection == NULL) {
DBUG_RETURN(NULL);
}//if
- NdbConnection* tConNext = theTransactionList;
+
+ theRemainingStartTransactions--;
+ NdbTransaction* tConNext = theTransactionList;
tConnection->init();
theTransactionList = tConnection; // into a transaction list.
tConnection->next(tConNext); // Add the active connection object
@@ -412,7 +454,7 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
theFirstTransId = tFirstTransId + 1;
}//if
#ifdef VM_TRACE
- if (tConnection->theListState != NdbConnection::NotInList) {
+ if (tConnection->theListState != NdbTransaction::NotInList) {
printState("startTransactionLocal %x", tConnection);
abort();
}
@@ -421,17 +463,17 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
}//Ndb::startTransactionLocal()
/*****************************************************************************
-void closeTransaction(NdbConnection* aConnection);
+void closeTransaction(NdbTransaction* aConnection);
Parameters: aConnection: the connection used in the transaction.
Remark: Close transaction by releasing the connection and all operations.
*****************************************************************************/
void
-Ndb::closeTransaction(NdbConnection* aConnection)
+Ndb::closeTransaction(NdbTransaction* aConnection)
{
DBUG_ENTER("Ndb::closeTransaction");
- NdbConnection* tCon;
- NdbConnection* tPreviousCon;
+ NdbTransaction* tCon;
+ NdbTransaction* tPreviousCon;
if (aConnection == NULL) {
//-----------------------------------------------------
@@ -446,6 +488,7 @@ Ndb::closeTransaction(NdbConnection* aConnection)
CHECK_STATUS_MACRO_VOID;
tCon = theTransactionList;
+ theRemainingStartTransactions++;
DBUG_PRINT("info",("close trans: 0x%x transid: 0x%llx",
aConnection, aConnection->getTransactionId()));
@@ -464,12 +507,12 @@ Ndb::closeTransaction(NdbConnection* aConnection)
if(aConnection->theError.code == 4008){
/**
- * When a SCAN timed-out, returning the NdbConnection leads
+ * When a SCAN timed-out, returning the NdbTransaction leads
* to reuse. And TC crashes when the API tries to reuse it to
* something else...
*/
#ifdef VM_TRACE
- printf("Scan timeout:ed NdbConnection-> "
+ printf("Scan timeout:ed NdbTransaction-> "
"not returning it-> memory leak\n");
#endif
DBUG_VOID_RETURN;
@@ -491,12 +534,12 @@ Ndb::closeTransaction(NdbConnection* aConnection)
if(aConnection->theError.code == 4008){
/**
- * Something timed-out, returning the NdbConnection leads
+ * Something timed-out, returning the NdbTransaction leads
* to reuse. And TC crashes when the API tries to reuse it to
* something else...
*/
#ifdef VM_TRACE
- printf("Con timeout:ed NdbConnection-> not returning it-> memory leak\n");
+ printf("Con timeout:ed NdbTransaction-> not returning it-> memory leak\n");
#endif
DBUG_VOID_RETURN;
}
@@ -535,7 +578,7 @@ Remark: Sends a signal to DIH.
int
Ndb::NdbTamper(TamperType aAction, int aNode)
{
- NdbConnection* tNdbConn;
+ NdbTransaction* tNdbConn;
NdbApiSignal tSignal(theMyRef);
int tNode;
int tAction;
@@ -577,7 +620,7 @@ Ndb::NdbTamper(TamperType aAction, int aNode)
tSignal.setData (tAction, 1);
tSignal.setData(tNdbConn->ptr2int(),2);
tSignal.setData(theMyRef,3); // Set return block reference
- tNdbConn->Status(NdbConnection::Connecting); // Set status to connecting
+ tNdbConn->Status(NdbTransaction::Connecting); // Set status to connecting
TransporterFacade *tp = TransporterFacade::instance();
if (tAction == 3) {
tp->lock_mutex();
@@ -610,7 +653,7 @@ Ndb::NdbTamper(TamperType aAction, int aNode)
}//if
ret_code = sendRecSignal(tNode, WAIT_NDB_TAMPER, &tSignal, 0);
if (ret_code == 0) {
- if (tNdbConn->Status() != NdbConnection::Connected) {
+ if (tNdbConn->Status() != NdbTransaction::Connected) {
theRestartGCI = 0;
}//if
releaseNdbCon(tNdbConn);
@@ -716,172 +759,226 @@ 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.
****************************************************************************/
-#define DEBUG_TRACE(msg) \
-// ndbout << __FILE__ << " line: " << __LINE__ << " msg: " << msg << endl
-
-Uint64
-Ndb::getAutoIncrementValue(const char* aTableName, Uint32 cacheSize)
+int
+Ndb::getAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId, Uint32 cacheSize)
{
- DBUG_ENTER("getAutoIncrementValue");
- const char * internalTableName = internalizeTableName(aTableName);
+ DBUG_ENTER("Ndb::getAutoIncrementValue");
+ BaseString internal_tabname(internalize_table_name(aTableName));
+
Ndb_local_table_info *info=
- theDictionary->get_local_table_info(internalTableName, false);
- if (info == 0)
- DBUG_RETURN(~(Uint64)0);
- const NdbTableImpl *table= info->m_table_impl;
- Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ theDictionary->get_local_table_info(internal_tabname, false);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable, Uint32 cacheSize)
+int
+Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId, Uint32 cacheSize)
{
- DBUG_ENTER("getAutoIncrementValue");
- if (aTable == 0)
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::getAutoIncrementValue");
+ assert(aTable != 0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- Uint64 tupleId = getTupleIdFromNdb(table->m_tableId, cacheSize);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
-}
+ const BaseString& internal_tabname = table->m_internalName;
-Uint64
-Ndb::getTupleIdFromNdb(const char* aTableName, Uint32 cacheSize)
-{
- const NdbTableImpl* table = theDictionary->getTable(aTableName);
- if (table == 0)
- return ~(Uint64)0;
- return getTupleIdFromNdb(table->m_tableId, cacheSize);
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname, false);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::getTupleIdFromNdb(Uint32 aTableId, Uint32 cacheSize)
+int
+Ndb::getTupleIdFromNdb(Ndb_local_table_info* info,
+ Uint64 & tupleId, Uint32 cacheSize)
{
- DBUG_ENTER("getTupleIdFromNdb");
- if ( theFirstTupleId[aTableId] != theLastTupleId[aTableId] )
+ DBUG_ENTER("Ndb::getTupleIdFromNdb");
+ if (info->m_first_tuple_id != info->m_last_tuple_id)
{
- theFirstTupleId[aTableId]++;
- DBUG_PRINT("info", ("next cached value %ul",
- (ulong) theFirstTupleId[aTableId]));
- DBUG_RETURN(theFirstTupleId[aTableId]);
+ assert(info->m_first_tuple_id < info->m_last_tuple_id);
+ tupleId = ++info->m_first_tuple_id;
+ DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId));
}
- else // theFirstTupleId == theLastTupleId
+ else
{
- DBUG_PRINT("info",("reading %u values from database",
- (cacheSize == 0) ? 1 : cacheSize));
- DBUG_RETURN(opTupleIdOnNdb(aTableId, (cacheSize == 0) ? 1 : cacheSize, 0));
+ if (cacheSize == 0)
+ cacheSize = 1;
+ DBUG_PRINT("info", ("reading %u values from database", (uint)cacheSize));
+ /*
+ * reserve next cacheSize entries in db. adds cacheSize to NEXTID
+ * and returns first tupleId in the new range.
+ */
+ Uint64 opValue = cacheSize;
+ if (opTupleIdOnNdb(info, opValue, 0) == -1)
+ DBUG_RETURN(-1);
+ tupleId = opValue;
}
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::readAutoIncrementValue(const char* aTableName)
+int
+Ndb::readAutoIncrementValue(const char* aTableName,
+ Uint64 & tupleId)
{
- DBUG_ENTER("readtAutoIncrementValue");
- const NdbTableImpl* table = theDictionary->getTable(aTableName);
- if (table == 0) {
- theError= theDictionary->getNdbError();
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::readAutoIncrementValue");
+ BaseString internal_tabname(internalize_table_name(aTableName));
+
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname, false);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
}
- Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ if (readTupleIdFromNdb(info, tupleId) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable)
+int
+Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 & tupleId)
{
- DBUG_ENTER("readtAutoIncrementValue");
- if (aTable == 0)
- DBUG_RETURN(~(Uint64)0);
+ DBUG_ENTER("Ndb::readAutoIncrementValue");
+ assert(aTable != 0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- Uint64 tupleId = readTupleIdFromNdb(table->m_tableId);
- DBUG_PRINT("info", ("value %ul", (ulong) tupleId));
- DBUG_RETURN(tupleId);
+ const BaseString& internal_tabname = table->m_internalName;
+
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname, false);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
+ }
+ if (readTupleIdFromNdb(info, tupleId) == -1)
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::readTupleIdFromNdb(Uint32 aTableId)
+int
+Ndb::readTupleIdFromNdb(Ndb_local_table_info* info,
+ Uint64 & tupleId)
{
- if ( theFirstTupleId[aTableId] == theLastTupleId[aTableId] )
- // Cache is empty, check next in database
- return opTupleIdOnNdb(aTableId, 0, 3);
-
- return theFirstTupleId[aTableId] + 1;
+ DBUG_ENTER("Ndb::readTupleIdFromNdb");
+ if (info->m_first_tuple_id != info->m_last_tuple_id)
+ {
+ assert(info->m_first_tuple_id < info->m_last_tuple_id);
+ tupleId = info->m_first_tuple_id + 1;
+ }
+ else
+ {
+ /*
+ * peek at NEXTID. does not reserve it so the value is valid
+ * only if no other transactions are allowed.
+ */
+ Uint64 opValue = 0;
+ if (opTupleIdOnNdb(info, opValue, 3) == -1)
+ DBUG_RETURN(-1);
+ tupleId = opValue;
+ }
+ DBUG_RETURN(0);
}
-bool
-Ndb::setAutoIncrementValue(const char* aTableName, Uint64 val, bool increase)
+int
+Ndb::setAutoIncrementValue(const char* aTableName,
+ Uint64 tupleId, bool increase)
{
- DEBUG_TRACE("setAutoIncrementValue " << val);
- const char * internalTableName= internalizeTableName(aTableName);
+ DBUG_ENTER("Ndb::setAutoIncrementValue");
+ BaseString internal_tabname(internalize_table_name(aTableName));
+
Ndb_local_table_info *info=
- theDictionary->get_local_table_info(internalTableName, false);
+ theDictionary->get_local_table_info(internal_tabname, false);
if (info == 0) {
- theError= theDictionary->getNdbError();
- return false;
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
}
- const NdbTableImpl* table= info->m_table_impl;
- return setTupleIdInNdb(table->m_tableId, val, increase);
+ if (setTupleIdInNdb(info, tupleId, increase) == -1)
+ DBUG_RETURN(-1);
+ DBUG_RETURN(0);
}
-bool
-Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, bool increase)
+int
+Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable,
+ Uint64 tupleId, bool increase)
{
- DEBUG_TRACE("setAutoIncrementValue " << val);
- if (aTable == 0)
- return ~(Uint64)0;
+ DBUG_ENTER("Ndb::setAutoIncrementValue");
+ assert(aTable != 0);
const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
- return setTupleIdInNdb(table->m_tableId, val, increase);
-}
+ const BaseString& internal_tabname = table->m_internalName;
-bool
-Ndb::setTupleIdInNdb(const char* aTableName, Uint64 val, bool increase )
-{
- DEBUG_TRACE("setTupleIdInNdb");
- const NdbTableImpl* table = theDictionary->getTable(aTableName);
- if (table == 0) {
- theError= theDictionary->getNdbError();
- return false;
+ Ndb_local_table_info *info=
+ theDictionary->get_local_table_info(internal_tabname, false);
+ if (info == 0) {
+ theError.code = theDictionary->getNdbError().code;
+ DBUG_RETURN(-1);
}
- return setTupleIdInNdb(table->m_tableId, val, increase);
+ if (setTupleIdInNdb(info, tupleId, increase) == -1)
+ DBUG_RETURN(-1);
+ DBUG_RETURN(0);
}
-bool
-Ndb::setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase )
+int
+Ndb::setTupleIdInNdb(Ndb_local_table_info* info,
+ Uint64 tupleId, bool increase)
{
- DEBUG_TRACE("setTupleIdInNdb");
+ DBUG_ENTER("Ndb::setTupleIdInNdb");
if (increase)
{
- if (theFirstTupleId[aTableId] != theLastTupleId[aTableId])
+ if (info->m_first_tuple_id != info->m_last_tuple_id)
{
- // We have a cache sequence
- if (val <= theFirstTupleId[aTableId]+1)
- return false;
- if (val <= theLastTupleId[aTableId])
+ assert(info->m_first_tuple_id < info->m_last_tuple_id);
+ if (tupleId <= info->m_first_tuple_id + 1)
+ DBUG_RETURN(0);
+ if (tupleId <= info->m_last_tuple_id)
{
- theFirstTupleId[aTableId] = val - 1;
- return true;
+ info->m_first_tuple_id = tupleId - 1;
+ DBUG_PRINT("info",
+ ("Setting next auto increment cached value to %llu",
+ (ulonglong)tupleId));
+ DBUG_RETURN(0);
}
- // else continue;
- }
- return (opTupleIdOnNdb(aTableId, val, 2) == val);
+ }
+ /*
+ * if tupleId <= NEXTID, do nothing. otherwise update NEXTID to
+ * tupleId and set cached range to first = last = tupleId - 1.
+ */
+ if (opTupleIdOnNdb(info, tupleId, 2) == -1)
+ DBUG_RETURN(-1);
}
else
- return (opTupleIdOnNdb(aTableId, val, 1) == val);
+ {
+ /*
+ * update NEXTID to given value. reset cached range.
+ */
+ if (opTupleIdOnNdb(info, tupleId, 1) == -1)
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
}
-Uint64
-Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
+int
+Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op)
{
- DEBUG_TRACE("opTupleIdOnNdb");
+ DBUG_ENTER("Ndb::opTupleIdOnNdb");
+ Uint32 aTableId = info->m_table_impl->m_tableId;
+ DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op));
- NdbConnection* tConnection;
- NdbOperation* tOperation;
+ NdbTransaction* tConnection;
+ NdbOperation* tOperation= 0; // Compiler warning if not initialized
Uint64 tValue;
NdbRecAttr* tRecAttrResult;
- int result;
- Uint64 ret;
CHECK_STATUS_MACRO_ZERO;
@@ -914,42 +1011,45 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
tValue = tRecAttrResult->u_64_value();
- theFirstTupleId[aTableId] = tValue - opValue;
- theLastTupleId[aTableId] = tValue - 1;
- ret = theFirstTupleId[aTableId];
+ info->m_first_tuple_id = tValue - opValue;
+ info->m_last_tuple_id = tValue - 1;
+ opValue = info->m_first_tuple_id; // out
break;
case 1:
- tOperation->updateTuple();
+ // create on first use
+ tOperation->writeTuple();
tOperation->equal("SYSKEY_0", aTableId );
tOperation->setValue("NEXTID", opValue);
if (tConnection->execute( Commit ) == -1 )
goto error_handler;
- theFirstTupleId[aTableId] = ~(Uint64)0;
- theLastTupleId[aTableId] = ~(Uint64)0;
- ret = opValue;
+ info->m_first_tuple_id = ~(Uint64)0;
+ info->m_last_tuple_id = ~(Uint64)0;
break;
case 2:
tOperation->interpretedUpdateTuple();
tOperation->equal("SYSKEY_0", aTableId );
tOperation->load_const_u64(1, opValue);
tOperation->read_attr("NEXTID", 2);
+ // compare NEXTID >= opValue
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;
+ if (tConnection->execute( Commit ) == -1)
+ {
+ if (tConnection->theError.code != 9999)
+ goto error_handler;
+ }
else
{
- theFirstTupleId[aTableId] = theLastTupleId[aTableId] = opValue - 1;
- ret = opValue;
+ DBUG_PRINT("info",
+ ("Setting next auto increment value (db) to %llu",
+ (ulonglong)opValue));
+ info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1;
}
break;
case 3:
@@ -958,7 +1058,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
tRecAttrResult = tOperation->getValue("NEXTID");
if (tConnection->execute( Commit ) == -1 )
goto error_handler;
- ret = tRecAttrResult->u_64_value();
+ opValue = tRecAttrResult->u_64_value(); // out
break;
default:
goto error_handler;
@@ -970,7 +1070,7 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
setDatabaseName(currentDb.c_str());
setDatabaseSchemaName(currentSchema.c_str());
- return ret;
+ DBUG_RETURN(0);
error_handler:
theError.code = tConnection->theError.code;
@@ -980,7 +1080,11 @@ Ndb::opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op)
setDatabaseName(currentDb.c_str());
setDatabaseSchemaName(currentSchema.c_str());
- return ~(Uint64)0;
+ DBUG_PRINT("error", ("ndb=%d con=%d op=%d",
+ theError.code,
+ tConnection ? tConnection->theError.code : -1,
+ tOperation ? tOperation->theError.code : -1));
+ DBUG_RETURN(-1);
}
Uint32
@@ -1002,39 +1106,31 @@ convertEndian(Uint32 Data)
}
const char * Ndb::getCatalogName() const
{
- return theDataBase;
+ return theImpl->m_dbname.c_str();
}
-
+
+
void Ndb::setCatalogName(const char * a_catalog_name)
{
- if (a_catalog_name) {
- BaseString::snprintf(theDataBase, sizeof(theDataBase), "%s",
- a_catalog_name ? a_catalog_name : "");
-
- int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
- theDataBase, table_name_separator,
- theDataBaseSchema, table_name_separator);
- prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
- sizeof(prefixName) - 1);
+ if (a_catalog_name)
+ {
+ theImpl->m_dbname.assign(a_catalog_name);
+ theImpl->update_prefix();
}
}
-
+
+
const char * Ndb::getSchemaName() const
{
- return theDataBaseSchema;
+ return theImpl->m_schemaname.c_str();
}
-
+
+
void Ndb::setSchemaName(const char * a_schema_name)
{
if (a_schema_name) {
- BaseString::snprintf(theDataBaseSchema, sizeof(theDataBase), "%s",
- a_schema_name ? a_schema_name : "");
-
- int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
- theDataBase, table_name_separator,
- theDataBaseSchema, table_name_separator);
- prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
- sizeof(prefixName) - 1);
+ theImpl->m_schemaname.assign(a_schema_name);
+ theImpl->update_prefix();
}
}
@@ -1111,35 +1207,63 @@ Ndb::externalizeIndexName(const char * internalIndexName)
return externalizeIndexName(internalIndexName, usingFullyQualifiedNames());
}
-const char *
-Ndb::internalizeTableName(const char * externalTableName)
+
+const BaseString
+Ndb::internalize_table_name(const char *external_name) const
{
- if (fullyQualifiedNames) {
- strncpy(prefixEnd, externalTableName, NDB_MAX_TAB_NAME_SIZE);
- return prefixName;
+ BaseString ret;
+ DBUG_ENTER("internalize_table_name");
+ DBUG_PRINT("enter", ("external_name: %s", external_name));
+
+ if (fullyQualifiedNames)
+ {
+ /* Internal table name format <db>/<schema>/<table>
+ <db>/<schema> is already available in m_prefix
+ so just concat the two strings
+ */
+ ret.assfmt("%s%s",
+ theImpl->m_prefix.c_str(),
+ external_name);
}
else
- return externalTableName;
+ ret.assign(external_name);
+
+ DBUG_PRINT("exit", ("internal_name: %s", ret.c_str()));
+ DBUG_RETURN(ret);
}
-
-const char *
-Ndb::internalizeIndexName(const NdbTableImpl * table,
- const char * externalIndexName)
+
+
+const BaseString
+Ndb::internalize_index_name(const NdbTableImpl * table,
+ const char * external_name) const
{
- if (fullyQualifiedNames) {
- char tableId[10];
- sprintf(tableId, "%d", table->m_tableId);
- Uint32 tabIdLen = strlen(tableId);
- strncpy(prefixEnd, tableId, tabIdLen);
- prefixEnd[tabIdLen] = table_name_separator;
- strncpy(prefixEnd + tabIdLen + 1,
- externalIndexName, NDB_MAX_TAB_NAME_SIZE);
- return prefixName;
+ BaseString ret;
+ DBUG_ENTER("internalize_index_name");
+ DBUG_PRINT("enter", ("external_name: %s, table_id: %d",
+ external_name, table ? table->m_tableId : ~0));
+ if (!table)
+ {
+ DBUG_PRINT("error", ("!table"));
+ return ret;
+ }
+
+ if (fullyQualifiedNames)
+ {
+ /* Internal index name format <db>/<schema>/<tabid>/<table> */
+ ret.assfmt("%s%d%c%s",
+ theImpl->m_prefix.c_str(),
+ table->m_tableId,
+ table_name_separator,
+ external_name);
}
else
- return externalIndexName;
+ ret.assign(external_name);
+
+ DBUG_PRINT("exit", ("internal_name: %s", ret.c_str()));
+ DBUG_RETURN(ret);
}
+
const BaseString
Ndb::getDatabaseFromInternalName(const char * internalName)
{
@@ -1175,50 +1299,12 @@ Ndb::getSchemaFromInternalName(const char * internalName)
return ret;
}
-NdbEventOperation* Ndb::createEventOperation(const char* eventName,
- const int bufferLength)
-{
- NdbEventOperation* tOp;
-
- tOp = new NdbEventOperation(this, eventName, bufferLength);
-
- if (tOp->getState() != NdbEventOperation::CREATED) {
- delete tOp;
- tOp = NULL;
- }
-
- //now we have to look up this event in dict
-
- return tOp;
-}
-
-int Ndb::dropEventOperation(NdbEventOperation* op) {
- delete op;
- return 0;
-}
-
-NdbGlobalEventBufferHandle* Ndb::getGlobalEventBufferHandle()
-{
- return theGlobalEventBufferHandle;
-}
-
-//void Ndb::monitorEvent(NdbEventOperation *op, NdbEventCallback cb, void* rs)
-//{
-//}
-
-int
-Ndb::pollEvents(int aMillisecondNumber)
-{
- return NdbEventOperation::wait(theGlobalEventBufferHandle,
- aMillisecondNumber);
-}
-
#ifdef VM_TRACE
#include <NdbMutex.h>
extern NdbMutex *ndb_print_state_mutex;
static bool
-checkdups(NdbConnection** list, unsigned no)
+checkdups(NdbTransaction** list, unsigned no)
{
for (unsigned i = 0; i < no; i++)
for (unsigned j = i + 1; j < no; j++)
@@ -1243,7 +1329,7 @@ Ndb::printState(const char* fmt, ...)
#endif
ndbout << endl;
for (unsigned n = 0; n < MAX_NDB_NODES; n++) {
- NdbConnection* con = theConnectionArray[n];
+ NdbTransaction* con = theConnectionArray[n];
if (con != 0) {
ndbout << "conn " << n << ":" << endl;
while (con != 0) {
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index 953d87ac7b0..94695185224 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -232,7 +232,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
theTrace = TestOrd::TraceAPI;
theReceiversBlockNumber = DBTC;
theVerId_signalNumber = GSN_TCINDXREQ;
- theLength = TcIndxReq::SignalLength;
+ theLength = TcKeyReq::SignalLength;
}
break;
diff --git a/ndb/src/ndbapi/NdbApiSignal.hpp b/ndb/src/ndbapi/NdbApiSignal.hpp
index 9a8326bd666..9d04a8594a8 100644
--- a/ndb/src/ndbapi/NdbApiSignal.hpp
+++ b/ndb/src/ndbapi/NdbApiSignal.hpp
@@ -94,7 +94,7 @@ private:
void setDataPtr(Uint32 *);
- friend class NdbConnection;
+ friend class NdbTransaction;
friend class NdbScanReceiver;
friend class Table;
void copyFrom(const NdbApiSignal * src);
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index e595b4b6472..fdee8961337 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -16,7 +16,7 @@
#include <Ndb.hpp>
#include <NdbDictionaryImpl.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include <NdbIndexOperation.hpp>
#include <NdbRecAttr.hpp>
@@ -25,34 +25,6 @@
#include <NdbScanOperation.hpp>
#include <signaldata/TcKeyReq.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; \
- 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)
-
-static char*
-ndb_blob_debug(const Uint32* data, unsigned size)
-{
- static char buf[200]; // MT irrelevant
- buf[0] = 0;
- for (unsigned i = 0; i < size; i++) {
- unsigned n = strlen(buf);
- if (n + 10 < sizeof(buf))
- sprintf(buf + n, "%*s%08x", i != 0, "", data[i]);
- }
- return buf;
-}
-
-#else
-#define DBG(x)
-#endif
-
/*
* Reading index table directly (as a table) is faster but there are
* bugs or limitations. Keep the code and make possible to choose.
@@ -64,8 +36,10 @@ static const bool g_ndb_blob_ok_to_read_index_table = false;
inline void
NdbBlob::setState(State newState)
{
- DBG("setState " << newState);
+ DBUG_ENTER("NdbBlob::setState");
+ DBUG_PRINT("info", ("this=%p newState=%u", this, newState));
theState = newState;
+ DBUG_VOID_RETURN;
}
// define blob table
@@ -101,8 +75,8 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
bt.setFragmentType(t->getFragmentType());
{ NdbDictionary::Column bc("PK");
bc.setType(NdbDictionary::Column::Unsigned);
- assert(t->m_sizeOfKeysInWords != 0);
- bc.setLength(t->m_sizeOfKeysInWords);
+ assert(t->m_keyLenInWords != 0);
+ bc.setLength(t->m_keyLenInWords);
bc.setPrimaryKey(true);
bc.setDistributionKey(true);
bt.addColumn(bc);
@@ -292,6 +266,16 @@ NdbBlob::isScanOp()
}
inline bool
+NdbBlob::isReadOnlyOp()
+{
+ return ! (
+ theNdbOp->theOperationType == NdbOperation::InsertRequest ||
+ theNdbOp->theOperationType == NdbOperation::UpdateRequest ||
+ theNdbOp->theOperationType == NdbOperation::WriteRequest
+ );
+}
+
+inline bool
NdbBlob::isTakeOverOp()
{
return
@@ -327,9 +311,9 @@ NdbBlob::getDistKey(Uint32 part)
int
NdbBlob::getTableKeyValue(NdbOperation* anOp)
{
+ DBUG_ENTER("NdbBlob::getTableKeyValue");
Uint32* data = (Uint32*)theKeyBuf.data;
unsigned pos = 0;
- DBG("getTableKeyValue");
for (unsigned i = 0; i < theTable->m_columns.size(); i++) {
NdbColumnImpl* c = theTable->m_columns[i];
assert(c != NULL);
@@ -337,7 +321,7 @@ NdbBlob::getTableKeyValue(NdbOperation* anOp)
unsigned len = c->m_attrSize * c->m_arraySize;
if (anOp->getValue_impl(c, (char*)&data[pos]) == NULL) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
// odd bytes receive no data and must be zeroed
while (len % 4 != 0) {
@@ -348,14 +332,15 @@ NdbBlob::getTableKeyValue(NdbOperation* anOp)
}
}
assert(pos == theKeyBuf.size / 4);
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setTableKeyValue(NdbOperation* anOp)
{
+ DBUG_ENTER("NdbBlob::setTableKeyValue");
+ DBUG_DUMP("info", theKeyBuf.data, 4 * theTable->m_keyLenInWords);
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;
for (unsigned i = 0; i < columns; i++) {
@@ -365,20 +350,21 @@ NdbBlob::setTableKeyValue(NdbOperation* anOp)
unsigned len = c->m_attrSize * c->m_arraySize;
if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
pos += (len + 3) / 4;
}
}
assert(pos == theKeyBuf.size / 4);
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setAccessKeyValue(NdbOperation* anOp)
{
+ DBUG_ENTER("NdbBlob::setAccessKeyValue");
+ DBUG_DUMP("info", theAccessKeyBuf.data, 4 * theAccessTable->m_keyLenInWords);
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;
for (unsigned i = 0; i < columns; i++) {
@@ -388,57 +374,60 @@ NdbBlob::setAccessKeyValue(NdbOperation* anOp)
unsigned len = c->m_attrSize * c->m_arraySize;
if (anOp->equal_impl(c, (const char*)&data[pos], len) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
pos += (len + 3) / 4;
}
}
assert(pos == theAccessKeyBuf.size / 4);
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
{
+ DBUG_ENTER("NdbBlob::setPartKeyValue");
+ DBUG_PRINT("info", ("dist=%u part=%u key=", getDistKey(part), part));
+ DBUG_DUMP("info", theKeyBuf.data, 4 * theTable->m_keyLenInWords);
Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
- DBG("setPartKeyValue dist=" << getDistKey(part) << " part=" << part << " key=" << ndb_blob_debug(data, size));
+ unsigned size = theTable->m_keyLenInWords;
// TODO use attr ids after compatibility with 4.1.7 not needed
if (anOp->equal("PK", theKeyBuf.data) == -1 ||
anOp->equal("DIST", getDistKey(part)) == -1 ||
anOp->equal("PART", part) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::getHeadInlineValue(NdbOperation* anOp)
{
- DBG("getHeadInlineValue");
+ DBUG_ENTER("NdbBlob::getHeadInlineValue");
theHeadInlineRecAttr = anOp->getValue_impl(theColumn, theHeadInlineBuf.data);
if (theHeadInlineRecAttr == NULL) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
void
NdbBlob::getHeadFromRecAttr()
{
+ DBUG_ENTER("NdbBlob::getHeadFromRecAttr");
assert(theHeadInlineRecAttr != NULL);
theNullFlag = theHeadInlineRecAttr->isNULL();
assert(theNullFlag != -1);
theLength = ! theNullFlag ? theHead->length : 0;
- DBG("getHeadFromRecAttr [out]");
+ DBUG_VOID_RETURN;
}
int
NdbBlob::setHeadInlineValue(NdbOperation* anOp)
{
- DBG("setHeadInlineValue");
+ DBUG_ENTER("NdbBlob::setHeadInlineValue");
theHead->length = theLength;
if (theLength < theInlineSize)
memset(theInlineData + theLength, 0, theInlineSize - theLength);
@@ -446,10 +435,10 @@ NdbBlob::setHeadInlineValue(NdbOperation* anOp)
const char* aValue = theNullFlag ? 0 : theHeadInlineBuf.data;
if (anOp->setValue(theColumn, aValue, theHeadInlineBuf.size) == -1) {
setErrorCode(anOp);
- return -1;
+ DBUG_RETURN(-1);
}
theHeadInlineUpdateFlag = false;
- return 0;
+ DBUG_RETURN(0);
}
// getValue/setValue
@@ -457,40 +446,42 @@ NdbBlob::setHeadInlineValue(NdbOperation* anOp)
int
NdbBlob::getValue(void* data, Uint32 bytes)
{
- DBG("getValue data=" << hex << data << " bytes=" << dec << bytes);
+ DBUG_ENTER("NdbBlob::getValue");
+ DBUG_PRINT("info", ("data=%p bytes=%u", data, bytes));
+ if (! isReadOp() && ! isScanOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theGetFlag || theState != Prepared) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
- }
- if (! isReadOp() && ! isScanOp()) {
- setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
if (data == NULL && bytes != 0) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
theGetFlag = true;
theGetBuf = static_cast<char*>(data);
theGetSetBytes = bytes;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setValue(const void* data, Uint32 bytes)
{
- DBG("setValue data=" << hex << data << " bytes=" << dec << bytes);
+ DBUG_ENTER("NdbBlob::setValue");
+ DBUG_PRINT("info", ("data=%p bytes=%u", data, bytes));
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theSetFlag || theState != Prepared) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
- }
- if (! isInsertOp() && ! isUpdateOp() && ! isWriteOp()) {
- setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
if (data == NULL && bytes != 0) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
theSetFlag = true;
theSetBuf = static_cast<const char*>(data);
@@ -503,15 +494,15 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
n = theInlineSize;
assert(thePos == 0);
if (writeDataPrivate(theSetBuf, n) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
theNullFlag = true;
theLength = 0;
}
if (setHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
// activation hook
@@ -519,14 +510,15 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
int
NdbBlob::setActiveHook(ActiveHook activeHook, void* arg)
{
- DBG("setActiveHook hook=" << hex << (void*)activeHook << " arg=" << hex << arg);
+ DBUG_ENTER("NdbBlob::setActiveHook");
+ DBUG_PRINT("info", ("hook=%p arg=%p", (void*)activeHook, arg));
if (theState != Prepared) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
theActiveHook = activeHook;
theActiveHookArg = arg;
- return 0;
+ DBUG_RETURN(0);
}
// misc operations
@@ -534,63 +526,72 @@ NdbBlob::setActiveHook(ActiveHook activeHook, void* arg)
int
NdbBlob::getNull(bool& isNull)
{
- DBG("getNull");
+ DBUG_ENTER("NdbBlob::getNull");
if (theState == Prepared && theSetFlag) {
isNull = (theSetBuf == NULL);
- return 0;
+ DBUG_RETURN(0);
}
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
isNull = theNullFlag;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setNull()
{
- DBG("setNull");
+ DBUG_ENTER("NdbBlob::setNull");
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theNullFlag == -1) {
if (theState == Prepared) {
- return setValue(0, 0);
+ DBUG_RETURN(setValue(0, 0));
}
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (theNullFlag)
- return 0;
+ DBUG_RETURN(0);
if (deleteParts(0, getPartCount()) == -1)
- return -1;
+ DBUG_RETURN(-1);
theNullFlag = true;
theLength = 0;
theHeadInlineUpdateFlag = true;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::getLength(Uint64& len)
{
- DBG("getLength");
+ DBUG_ENTER("NdbBlob::getLength");
if (theState == Prepared && theSetFlag) {
len = theGetSetBytes;
- return 0;
+ DBUG_RETURN(0);
}
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
len = theLength;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::truncate(Uint64 length)
{
- DBG("truncate [in] length=" << length);
+ DBUG_ENTER("NdbBlob::truncate");
+ DBUG_PRINT("info", ("length=%llu", length));
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (theLength > length) {
if (length > theInlineSize) {
@@ -598,46 +599,46 @@ NdbBlob::truncate(Uint64 length)
Uint32 part2 = getPartNumber(theLength - 1);
assert(part2 >= part1);
if (part2 > part1 && deleteParts(part1 + 1, part2 - part1) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (deleteParts(0, getPartCount()) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
theLength = length;
theHeadInlineUpdateFlag = true;
if (thePos > length)
thePos = length;
}
- DBG("truncate [out]");
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::getPos(Uint64& pos)
{
- DBG("getPos");
+ DBUG_ENTER("NdbBlob::getPos");
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
pos = thePos;
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::setPos(Uint64 pos)
{
- DBG("setPos pos=" << pos);
+ DBUG_ENTER("NdbBlob::setPos");
+ DBUG_PRINT("info", ("pos=%llu", pos));
if (theNullFlag == -1) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
if (pos > theLength) {
setErrorCode(NdbBlobImpl::ErrSeek);
- return -1;
+ DBUG_RETURN(-1);
}
thePos = pos;
- return 0;
+ DBUG_RETURN(0);
}
// read/write
@@ -645,18 +646,21 @@ NdbBlob::setPos(Uint64 pos)
int
NdbBlob::readData(void* data, Uint32& bytes)
{
+ DBUG_ENTER("NdbBlob::readData");
if (theState != Active) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
char* buf = static_cast<char*>(data);
- return readDataPrivate(buf, bytes);
+ int ret = readDataPrivate(buf, bytes);
+ DBUG_RETURN(ret);
}
int
NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
{
- DBG("readData [in] bytes=" << bytes);
+ DBUG_ENTER("NdbBlob::readDataPrivate");
+ DBUG_PRINT("info", ("bytes=%u", bytes));
assert(thePos <= theLength);
Uint64 pos = thePos;
if (bytes > theLength - pos)
@@ -676,20 +680,20 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
}
if (len > 0 && thePartSize == 0) {
setErrorCode(NdbBlobImpl::ErrSeek);
- return -1;
+ DBUG_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);
+ DBUG_PRINT("info", ("partial first block pos=%llu len=%u", pos, len));
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 n = thePartSize - off;
if (n > len)
n = len;
@@ -706,7 +710,7 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
Uint32 part = (pos - theInlineSize) / thePartSize;
Uint32 count = len / thePartSize;
if (readParts(buf, part, count) == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 n = thePartSize * count;
pos += n;
buf += n;
@@ -715,14 +719,14 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
}
if (len > 0) {
// partial last block
- DBG("partial last block pos=" << pos << " len=" << len);
+ DBUG_PRINT("info", ("partial last block pos=%llu len=%u", pos, len));
assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
memcpy(buf, thePartBuf.data, len);
Uint32 n = len;
pos += n;
@@ -732,25 +736,31 @@ NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
assert(len == 0);
thePos = pos;
assert(thePos <= theLength);
- DBG("readData [out]");
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::writeData(const void* data, Uint32 bytes)
{
+ DBUG_ENTER("NdbBlob::writeData");
+ if (isReadOnlyOp()) {
+ setErrorCode(NdbBlobImpl::ErrCompat);
+ DBUG_RETURN(-1);
+ }
if (theState != Active) {
setErrorCode(NdbBlobImpl::ErrState);
- return -1;
+ DBUG_RETURN(-1);
}
const char* buf = static_cast<const char*>(data);
- return writeDataPrivate(buf, bytes);
+ int ret = writeDataPrivate(buf, bytes);
+ DBUG_RETURN(ret);
}
int
NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
{
- DBG("writeData [in] bytes=" << bytes);
+ DBUG_ENTER("NdbBlob::writeDataPrivate");
+ DBUG_PRINT("info", ("bytes=%u", bytes));
assert(thePos <= theLength);
Uint64 pos = thePos;
Uint32 len = bytes;
@@ -774,23 +784,23 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
if (len > 0 && thePartSize == 0) {
setErrorCode(NdbBlobImpl::ErrSeek);
- return -1;
+ DBUG_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);
+ DBUG_PRINT("info", ("partial first block pos=%llu len=%u", pos, len));
// flush writes to guarantee correct read
if (executePendingBlobWrites() == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
Uint32 n = thePartSize - off;
if (n > len) {
memset(thePartBuf.data + off + len, theFillChar, n - len);
@@ -798,7 +808,7 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
memcpy(thePartBuf.data + off, buf, n);
if (updateParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
pos += n;
buf += n;
len -= n;
@@ -813,10 +823,10 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
for (unsigned i = 0; i < count; i++) {
if (part + i < getPartCount()) {
if (updateParts(buf, part + i, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (insertParts(buf, part + i, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
Uint32 n = thePartSize;
pos += n;
@@ -827,30 +837,30 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
if (len > 0) {
// partial last block
- DBG("partial last block pos=" << pos << " len=" << len);
+ DBUG_PRINT("info", ("partial last block pos=%llu len=%u", pos, len));
assert((pos - theInlineSize) % thePartSize == 0 && len < thePartSize);
Uint32 part = (pos - theInlineSize) / thePartSize;
if (theLength > pos + len) {
// flush writes to guarantee correct read
if (executePendingBlobWrites() == -1)
- return -1;
+ DBUG_RETURN(-1);
if (readParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
// need result now
if (executePendingBlobReads() == -1)
- return -1;
+ DBUG_RETURN(-1);
memcpy(thePartBuf.data, buf, len);
if (updateParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
memcpy(thePartBuf.data, buf, len);
memset(thePartBuf.data + len, theFillChar, thePartSize - len);
if (part < getPartCount()) {
if (updateParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (insertParts(thePartBuf.data, part, 1) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
Uint32 n = len;
@@ -865,14 +875,14 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
}
thePos = pos;
assert(thePos <= theLength);
- DBG("writeData [out]");
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
{
- DBG("readParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::readParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -881,21 +891,22 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
setPartKeyValue(tOp, part + n) == -1 ||
tOp->getValue((Uint32)3, buf) == NULL) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
{
- DBG("insertParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::insertParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -904,21 +915,22 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
setPartKeyValue(tOp, part + n) == -1 ||
tOp->setValue((Uint32)3, buf) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
{
- DBG("updateParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::updateParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -927,21 +939,22 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
setPartKeyValue(tOp, part + n) == -1 ||
tOp->setValue((Uint32)3, buf) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::deleteParts(Uint32 part, Uint32 count)
{
- DBG("deleteParts [in] part=" << part << " count=" << count);
+ DBUG_ENTER("NdbBlob::deleteParts");
+ DBUG_PRINT("info", ("part=%u count=%u", part, count));
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -949,14 +962,14 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
tOp->deleteTuple() == -1 ||
setPartKeyValue(tOp, part + n) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
n++;
thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
}
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -966,9 +979,10 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
int
NdbBlob::deletePartsUnknown(Uint32 part)
{
- DBG("deletePartsUnknown [in] part=" << part << " count=all");
+ DBUG_ENTER("NdbBlob::deletePartsUnknown");
+ DBUG_PRINT("info", ("part=%u count=all", part));
if (thePartSize == 0) // tinyblob
- return 0;
+ DBUG_RETURN(0);
static const unsigned maxbat = 256;
static const unsigned minbat = 1;
unsigned bat = minbat;
@@ -984,26 +998,25 @@ NdbBlob::deletePartsUnknown(Uint32 part)
tOp->deleteTuple() == -1 ||
setPartKeyValue(tOp, part + count + n) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AO_IgnoreError;
+ tOp->m_abortOption= NdbTransaction::AO_IgnoreError;
n++;
}
- DBG("deletePartsUnknown: executeNoBlobs [in] bat=" << bat);
- if (theNdbCon->executeNoBlobs(NoCommit) == -1)
- return -1;
- DBG("deletePartsUnknown: executeNoBlobs [out]");
+ DBUG_PRINT("info", ("bat=%u", bat));
+ if (theNdbCon->executeNoBlobs(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
n = 0;
while (n < bat) {
NdbOperation* tOp = tOpList[n];
if (tOp->theError.code != 0) {
if (tOp->theError.code != 626) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
// first non-existent part
- DBG("deletePartsUnknown [out] count=" << count);
- return 0;
+ DBUG_PRINT("info", ("count=%u", count));
+ DBUG_RETURN(0);
}
n++;
count++;
@@ -1019,31 +1032,29 @@ NdbBlob::deletePartsUnknown(Uint32 part)
int
NdbBlob::executePendingBlobReads()
{
+ DBUG_ENTER("NdbBlob::executePendingBlobReads");
Uint8 flags = (1 << NdbOperation::ReadRequest);
if (thePendingBlobOps & flags) {
- DBG("executePendingBlobReads: executeNoBlobs [in]");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1)
- return -1;
- DBG("executePendingBlobReads: executeNoBlobs [out]");
+ if (theNdbCon->executeNoBlobs(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
thePendingBlobOps = 0;
theNdbCon->thePendingBlobOps = 0;
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbBlob::executePendingBlobWrites()
{
+ DBUG_ENTER("NdbBlob::executePendingBlobWrites");
Uint8 flags = 0xFF & ~(1 << NdbOperation::ReadRequest);
if (thePendingBlobOps & flags) {
- DBG("executePendingBlobWrites: executeNoBlobs [in]");
- if (theNdbCon->executeNoBlobs(NoCommit) == -1)
- return -1;
- DBG("executePendingBlobWrites: executeNoBlobs [out]");
+ if (theNdbCon->executeNoBlobs(NdbTransaction::NoCommit) == -1)
+ DBUG_RETURN(-1);
thePendingBlobOps = 0;
theNdbCon->thePendingBlobOps = 0;
}
- return 0;
+ DBUG_RETURN(0);
}
// callbacks
@@ -1051,15 +1062,14 @@ NdbBlob::executePendingBlobWrites()
int
NdbBlob::invokeActiveHook()
{
- DBG("invokeActiveHook [in]");
+ DBUG_ENTER("NdbBlob::invokeActiveHook");
assert(theState == Active && theActiveHook != NULL);
int ret = (*theActiveHook)(this, theActiveHookArg);
- DBG("invokeActiveHook [out] ret=" << ret);
if (ret != 0) {
// no error is set on blob level
- return -1;
+ DBUG_RETURN(-1);
}
- return 0;
+ DBUG_RETURN(0);
}
// blob handle maintenance
@@ -1070,8 +1080,10 @@ NdbBlob::invokeActiveHook()
* data. For read operation adds read of head+inline.
*/
int
-NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn)
+NdbBlob::atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn)
{
+ DBUG_ENTER("NdbBlob::atPrepare");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, anOp, aCon));
assert(theState == Idle);
// ndb api stuff
theNdb = anOp->theNdb;
@@ -1080,7 +1092,6 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theTable = anOp->m_currentTable;
theAccessTable = anOp->m_accessTable;
theColumn = aColumn;
- DBG("atPrepare [in]");
NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined;
switch (theColumn->getType()) {
case NdbDictionary::Column::Blob:
@@ -1093,7 +1104,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
break;
default:
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
// sizes
theInlineSize = theColumn->getInlineSize();
@@ -1111,13 +1122,13 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
bc->getType() != partType ||
bc->getLength() != (int)thePartSize) {
setErrorCode(NdbBlobImpl::ErrTable);
- return -1;
+ DBUG_RETURN(-1);
}
theBlobTable = &NdbTableImpl::getImpl(*bt);
}
// buffers
- theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2);
- theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2);
+ theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+ theAccessKeyBuf.alloc(theAccessTable->m_keyLenInWords << 2);
theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
theHeadInlineCopyBuf.alloc(sizeof(Head) + theInlineSize);
thePartBuf.alloc(thePartSize);
@@ -1129,25 +1140,28 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
if (isTableOp()) {
// get table key
Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isIndexOp()) {
// get index key
Uint32* data = (Uint32*)theAccessKeyBuf.data;
- unsigned size = theAccessTable->m_sizeOfKeysInWords;
+ unsigned size = theAccessTable->m_keyLenInWords;
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isReadOp()) {
+ // upgrade lock mode
+ if (theNdbOp->theLockMode == NdbOperation::LM_CommittedRead)
+ theNdbOp->theLockMode = NdbOperation::LM_Read;
// add read of head+inline in this op
if (getHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
if (isInsertOp()) {
// becomes NULL unless set before execute
@@ -1163,18 +1177,20 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
supportedOp = true;
}
if (isScanOp()) {
+ // upgrade lock mode
+ if (theNdbOp->theLockMode == NdbOperation::LM_CommittedRead)
+ theNdbOp->theLockMode = NdbOperation::LM_Read;
// add read of head+inline in this op
if (getHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
supportedOp = true;
}
if (! supportedOp) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
setState(Prepared);
- DBG("atPrepare [out]");
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -1185,11 +1201,12 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
* back after postExecute.
*/
int
-NdbBlob::preExecute(ExecType anExecType, bool& batch)
+NdbBlob::preExecute(NdbTransaction::ExecType anExecType, bool& batch)
{
- DBG("preExecute [in]");
+ DBUG_ENTER("NdbBlob::preExecute");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, theNdbOp, theNdbCon));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
assert(theState == Prepared);
// handle different operation types
assert(isKeyOp());
@@ -1207,7 +1224,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
Uint32 bytes = theGetSetBytes - theInlineSize;
assert(thePos == theInlineSize);
if (writeDataPrivate(buf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theHeadInlineUpdateFlag) {
// add an operation to update head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
@@ -1216,9 +1233,9 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setTableKeyValue(tOp) == -1 ||
setHeadInlineValue(tOp) == -1) {
setErrorCode(NdbBlobImpl::ErrAbort);
- return -1;
+ DBUG_RETURN(-1);
}
- DBG("add op to update head+inline");
+ DBUG_PRINT("info", ("add op to update head+inline"));
}
}
}
@@ -1245,15 +1262,15 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setTableKeyValue(tOp) == -1 ||
getHeadInlineValue(tOp) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
if (isWriteOp()) {
- tOp->m_abortOption = AO_IgnoreError;
+ tOp->m_abortOption = NdbTransaction::AO_IgnoreError;
}
theHeadInlineReadOp = tOp;
// execute immediately
batch = true;
- DBG("add op before to read head+inline");
+ DBUG_PRINT("info", ("add op before to read head+inline"));
}
}
if (isIndexOp()) {
@@ -1269,7 +1286,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setAccessKeyValue(tOp) == -1 ||
tOp->getValue(pkAttrId, theKeyBuf.data) == NULL) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
} else {
NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
@@ -1278,11 +1295,11 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setAccessKeyValue(tOp) == -1 ||
getTableKeyValue(tOp) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
}
}
- DBG("added op before to read table key");
+ DBUG_PRINT("info", ("added op before to read table key"));
if (isUpdateOp() || isDeleteOp()) {
// add op before this one to read head+inline via index
NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
@@ -1291,15 +1308,15 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setAccessKeyValue(tOp) == -1 ||
getHeadInlineValue(tOp) == -1) {
setErrorCode(tOp);
- return -1;
+ DBUG_RETURN(-1);
}
if (isWriteOp()) {
- tOp->m_abortOption = AO_IgnoreError;
+ tOp->m_abortOption = NdbTransaction::AO_IgnoreError;
}
theHeadInlineReadOp = tOp;
// execute immediately
batch = true;
- DBG("added index op before to read head+inline");
+ DBUG_PRINT("info", ("added index op before to read head+inline"));
}
if (isWriteOp()) {
// XXX until IgnoreError fixed for index op
@@ -1317,10 +1334,10 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
n = theInlineSize;
assert(thePos == 0);
if (writeDataPrivate(theSetBuf, n) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
if (setHeadInlineValue(theNdbOp) == -1)
- return -1;
+ DBUG_RETURN(-1);
// the read op before us may overwrite
theHeadInlineCopyBuf.copyfrom(theHeadInlineBuf);
}
@@ -1329,8 +1346,8 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
// need blob head for callback
batch = true;
}
- DBG("preExecute [out] batch=" << batch);
- return 0;
+ DBUG_PRINT("info", ("batch=%u", batch));
+ DBUG_RETURN(0);
}
/*
@@ -1340,18 +1357,19 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
* any remaining prepared operations.
*/
int
-NdbBlob::postExecute(ExecType anExecType)
+NdbBlob::postExecute(NdbTransaction::ExecType anExecType)
{
- DBG("postExecute [in] type=" << anExecType);
+ DBUG_ENTER("NdbBlob::postExecute");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p anExecType=%u", this, theNdbOp, theNdbCon, anExecType));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
if (theState == Active) {
- setState(anExecType == NoCommit ? Active : Closed);
- DBG("postExecute [skip]");
- return 0;
+ setState(anExecType == NdbTransaction::NoCommit ? Active : Closed);
+ DBUG_PRINT("info", ("skip active"));
+ DBUG_RETURN(0);
}
assert(theState == Prepared);
- setState(anExecType == NoCommit ? Active : Closed);
+ setState(anExecType == NdbTransaction::NoCommit ? Active : Closed);
assert(isKeyOp());
if (isIndexOp()) {
NdbBlob* tFirstBlob = theNdbOp->theBlobList;
@@ -1364,42 +1382,43 @@ NdbBlob::postExecute(ExecType anExecType)
if (isReadOp()) {
getHeadFromRecAttr();
if (setPos(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theGetFlag) {
assert(theGetSetBytes == 0 || theGetBuf != 0);
- assert(theGetSetBytes <= theInlineSize || anExecType == NoCommit);
+ assert(theGetSetBytes <= theInlineSize ||
+ anExecType == NdbTransaction::NoCommit);
Uint32 bytes = theGetSetBytes;
if (readDataPrivate(theGetBuf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isUpdateOp()) {
- assert(anExecType == NoCommit);
+ assert(anExecType == NdbTransaction::NoCommit);
getHeadFromRecAttr();
if (theSetFlag) {
// setValue overwrites everything
if (theSetBuf != NULL) {
if (truncate(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
assert(thePos == 0);
if (writeDataPrivate(theSetBuf, theGetSetBytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
} else {
if (setNull() == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
}
if (isWriteOp() && isTableOp()) {
- assert(anExecType == NoCommit);
+ assert(anExecType == NdbTransaction::NoCommit);
if (theHeadInlineReadOp->theError.code == 0) {
int tNullFlag = theNullFlag;
Uint64 tLength = theLength;
Uint64 tPos = thePos;
getHeadFromRecAttr();
- DBG("tuple found");
+ DBUG_PRINT("info", ("tuple found"));
if (truncate(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
// restore previous head+inline
theHeadInlineBuf.copyfrom(theHeadInlineCopyBuf);
theNullFlag = tNullFlag;
@@ -1408,16 +1427,16 @@ NdbBlob::postExecute(ExecType anExecType)
} else {
if (theHeadInlineReadOp->theError.code != 626) {
setErrorCode(theHeadInlineReadOp);
- return -1;
+ DBUG_RETURN(-1);
}
- DBG("tuple not found");
+ DBUG_PRINT("info", ("tuple not found"));
/*
* Read found no tuple but it is possible that a tuple was
* created after the read by another transaction. Delete all
* blob parts which may exist.
*/
if (deletePartsUnknown(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
if (theSetFlag && theGetSetBytes > theInlineSize) {
assert(theSetBuf != NULL);
@@ -1425,48 +1444,47 @@ NdbBlob::postExecute(ExecType anExecType)
Uint32 bytes = theGetSetBytes - theInlineSize;
assert(thePos == theInlineSize);
if (writeDataPrivate(buf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isWriteOp() && isIndexOp()) {
// XXX until IgnoreError fixed for index op
if (deletePartsUnknown(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theSetFlag && theGetSetBytes > theInlineSize) {
assert(theSetBuf != NULL);
const char* buf = theSetBuf + theInlineSize;
Uint32 bytes = theGetSetBytes - theInlineSize;
assert(thePos == theInlineSize);
if (writeDataPrivate(buf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
}
if (isDeleteOp()) {
- assert(anExecType == NoCommit);
+ assert(anExecType == NdbTransaction::NoCommit);
getHeadFromRecAttr();
if (deleteParts(0, getPartCount()) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- setState(anExecType == NoCommit ? Active : Closed);
+ setState(anExecType == NdbTransaction::NoCommit ? Active : Closed);
// activation callback
if (theActiveHook != NULL) {
if (invokeActiveHook() == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- if (anExecType == NoCommit && theHeadInlineUpdateFlag) {
+ if (anExecType == NdbTransaction::NoCommit && theHeadInlineUpdateFlag) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
if (tOp == NULL ||
tOp->updateTuple() == -1 ||
setTableKeyValue(tOp) == -1 ||
setHeadInlineValue(tOp) == -1) {
setErrorCode(NdbBlobImpl::ErrAbort);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
- DBG("added op to update head+inline");
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
+ DBUG_PRINT("info", ("added op to update head+inline"));
}
- DBG("postExecute [out]");
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -1476,9 +1494,10 @@ NdbBlob::postExecute(ExecType anExecType)
int
NdbBlob::preCommit()
{
- DBG("preCommit [in]");
+ DBUG_ENTER("NdbBlob::preCommit");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, theNdbOp, theNdbCon));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
assert(theState == Active);
assert(isKeyOp());
if (isInsertOp() || isUpdateOp() || isWriteOp()) {
@@ -1490,14 +1509,13 @@ NdbBlob::preCommit()
setTableKeyValue(tOp) == -1 ||
setHeadInlineValue(tOp) == -1) {
setErrorCode(NdbBlobImpl::ErrAbort);
- return -1;
+ DBUG_RETURN(-1);
}
- tOp->m_abortOption = AbortOnError;
- DBG("added op to update head+inline");
+ tOp->m_abortOption = NdbTransaction::AbortOnError;
+ DBUG_PRINT("info", ("added op to update head+inline"));
}
}
- DBG("preCommit [out]");
- return 0;
+ DBUG_RETURN(0);
}
/*
@@ -1506,35 +1524,35 @@ NdbBlob::preCommit()
int
NdbBlob::atNextResult()
{
- DBG("atNextResult [in]");
+ DBUG_ENTER("NdbBlob::atNextResult");
+ DBUG_PRINT("info", ("this=%p op=%p con=%p", this, theNdbOp, theNdbCon));
if (theState == Invalid)
- return -1;
+ DBUG_RETURN(-1);
assert(isScanOp());
// get primary key
{ Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
setErrorCode(NdbBlobImpl::ErrUsage);
- return -1;
+ DBUG_RETURN(-1);
}
}
getHeadFromRecAttr();
if (setPos(0) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (theGetFlag) {
assert(theGetSetBytes == 0 || theGetBuf != 0);
Uint32 bytes = theGetSetBytes;
if (readDataPrivate(theGetBuf, bytes) == -1)
- return -1;
+ DBUG_RETURN(-1);
}
setState(Active);
// activation callback
if (theActiveHook != NULL) {
if (invokeActiveHook() == -1)
- return -1;
+ DBUG_RETURN(-1);
}
- DBG("atNextResult [out]");
- return 0;
+ DBUG_RETURN(0);
}
// misc
@@ -1550,13 +1568,15 @@ NdbBlob::getColumn()
void
NdbBlob::setErrorCode(int anErrorCode, bool invalidFlag)
{
- DBG("setErrorCode code=" << anErrorCode);
+ DBUG_ENTER("NdbBlob::setErrorCode");
+ DBUG_PRINT("info", ("this=%p code=%u", this, 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);
+ DBUG_VOID_RETURN;
}
void
@@ -1575,7 +1595,7 @@ NdbBlob::setErrorCode(NdbOperation* anOp, bool invalidFlag)
}
void
-NdbBlob::setErrorCode(NdbConnection* aCon, bool invalidFlag)
+NdbBlob::setErrorCode(NdbTransaction* aCon, bool invalidFlag)
{
int code = 0;
if (theNdbCon != NULL && (code = theNdbCon->theError.code) != 0)
diff --git a/ndb/src/ndbapi/NdbBlobImpl.hpp b/ndb/src/ndbapi/NdbBlobImpl.hpp
index 0030e910c52..b56aabfd84e 100644
--- a/ndb/src/ndbapi/NdbBlobImpl.hpp
+++ b/ndb/src/ndbapi/NdbBlobImpl.hpp
@@ -24,7 +24,7 @@ public:
STATIC_CONST( ErrTable = 4263 );
// "Invalid usage of blob attribute"
STATIC_CONST( ErrUsage = 4264 );
- // "Method is not valid in current blob state"
+ // "The blob method is not valid in current blob state"
STATIC_CONST( ErrState = 4265 );
// "Invalid blob seek position"
STATIC_CONST( ErrSeek = 4266 );
@@ -33,7 +33,9 @@ public:
// "Error in blob head update forced rollback of transaction"
STATIC_CONST( ErrAbort = 4268 );
// "Unknown blob error"
- STATIC_CONST( ErrUnknown = 4269 );
+ STATIC_CONST( ErrUnknown = 4270 );
+ // "The blob method is incompatible with operation type or lock mode"
+ STATIC_CONST( ErrCompat = 4275 );
};
#endif
diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp
index 8ed85995d69..6c721b76ba0 100644
--- a/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/ndb/src/ndbapi/NdbDictionary.cpp
@@ -176,52 +176,16 @@ NdbDictionary::Column::getPrimaryKey() const {
return m_impl.m_pk;
}
-void
-NdbDictionary::Column::setTupleKey(bool val){
- m_impl.m_tupleKey = val;
-}
-
-bool
-NdbDictionary::Column::getTupleKey() const {
- return m_impl.m_tupleKey;
-}
-
void
-NdbDictionary::Column::setDistributionKey(bool val){
+NdbDictionary::Column::setPartitionKey(bool val){
m_impl.m_distributionKey = val;
}
bool
-NdbDictionary::Column::getDistributionKey() const{
+NdbDictionary::Column::getPartitionKey() const{
return m_impl.m_distributionKey;
}
-void
-NdbDictionary::Column::setDistributionGroup(bool val, int bits){
- m_impl.m_distributionGroup = val;
- m_impl.m_distributionGroupBits = bits;
-}
-
-bool
-NdbDictionary::Column::getDistributionGroup() const {
- return m_impl.m_distributionGroup;
-}
-
-int
-NdbDictionary::Column::getDistributionGroupBits() const{
- return m_impl.m_distributionGroupBits;
-}
-
-void
-NdbDictionary::Column::setIndexOnlyStorage(bool val){
- m_impl.m_indexOnly = val;
-}
-
-bool
-NdbDictionary::Column::getIndexOnlyStorage() const {
- return m_impl.m_indexOnly;
-}
-
const NdbDictionary::Table *
NdbDictionary::Column::getBlobTable() const {
NdbTableImpl * t = m_impl.m_blobTable;
@@ -267,6 +231,12 @@ NdbDictionary::Column::equal(const NdbDictionary::Column & col) const {
return m_impl.equal(col.m_impl);
}
+int
+NdbDictionary::Column::getSizeInBytes() const
+{
+ return m_impl.m_attrSize * m_impl.m_arraySize;
+}
+
/*****************************************************************
* Table facade
*/
@@ -415,6 +385,30 @@ NdbDictionary::Table::getNoOfPrimaryKeys() const {
return m_impl.m_noOfKeys;
}
+void
+NdbDictionary::Table::setMaxRows(Uint64 maxRows)
+{
+ m_impl.m_max_rows = maxRows;
+}
+
+Uint64
+NdbDictionary::Table::getMaxRows() const
+{
+ return m_impl.m_max_rows;
+}
+
+void
+NdbDictionary::Table::setMinRows(Uint64 minRows)
+{
+ m_impl.m_min_rows = minRows;
+}
+
+Uint64
+NdbDictionary::Table::getMinRows() const
+{
+ return m_impl.m_min_rows;
+}
+
const char*
NdbDictionary::Table::getPrimaryKey(int no) const {
int count = 0;
@@ -462,13 +456,17 @@ NdbDictionary::Table::getRowSizeInBytes() const {
int sz = 0;
for(int i = 0; i<getNoOfColumns(); i++){
const NdbDictionary::Column * c = getColumn(i);
- const NdbColumnImpl & col = NdbColumnImpl::getImpl(* c);
- sz += (((col.m_attrSize * col.m_arraySize) + 3) / 4);
+ sz += (c->getSizeInBytes()+ 3) / 4;
}
return sz * 4;
}
int
+NdbDictionary::Table::getReplicaCount() const {
+ return m_impl.m_replicaCount;
+}
+
+int
NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const {
const NdbDictionary::Table * pTab =
pNdb->getDictionary()->getTable(getName());
@@ -613,96 +611,6 @@ NdbDictionary::Index::getObjectVersion() const {
}
/*****************************************************************
- * Event facade
- */
-NdbDictionary::Event::Event(const char * name)
- : m_impl(* new NdbEventImpl(* this))
-{
- setName(name);
-}
-
-NdbDictionary::Event::Event(NdbEventImpl & impl)
- : m_impl(impl)
-{
-}
-
-NdbDictionary::Event::~Event()
-{
- NdbEventImpl * tmp = &m_impl;
- if(this != tmp){
- delete tmp;
- }
-}
-
-void
-NdbDictionary::Event::setName(const char * name)
-{
- m_impl.setName(name);
-}
-
-void
-NdbDictionary::Event::setTable(const char * table)
-{
- m_impl.setTable(table);
-}
-
-void
-NdbDictionary::Event::addTableEvent(const TableEvent t)
-{
- m_impl.addTableEvent(t);
-}
-
-void
-NdbDictionary::Event::setDurability(const EventDurability d)
-{
- m_impl.setDurability(d);
-}
-
-void
-NdbDictionary::Event::addColumn(const Column & c){
- NdbColumnImpl* col = new NdbColumnImpl;
- (* col) = NdbColumnImpl::getImpl(c);
- m_impl.m_columns.push_back(col);
-}
-
-void
-NdbDictionary::Event::addEventColumn(unsigned attrId)
-{
- m_impl.m_attrIds.push_back(attrId);
-}
-
-void
-NdbDictionary::Event::addEventColumn(const char * name)
-{
- const Column c(name);
- addColumn(c);
-}
-
-void
-NdbDictionary::Event::addEventColumns(int n, const char ** names)
-{
- for (int i = 0; i < n; i++)
- addEventColumn(names[i]);
-}
-
-NdbDictionary::Object::Status
-NdbDictionary::Event::getObjectStatus() const
-{
- return m_impl.m_status;
-}
-
-int
-NdbDictionary::Event::getObjectVersion() const
-{
- return m_impl.m_version;
-}
-
-void NdbDictionary::Event::print()
-{
- m_impl.print();
-}
-
-/*****************************************************************
* Dictionary facade
*/
NdbDictionary::Dictionary::Dictionary(Ndb & ndb)
@@ -742,7 +650,8 @@ NdbDictionary::Dictionary::alterTable(const Table & t){
}
const NdbDictionary::Table *
-NdbDictionary::Dictionary::getTable(const char * name, void **data){
+NdbDictionary::Dictionary::getTable(const char * name, void **data) const
+{
NdbTableImpl * t = m_impl.getTable(name, data);
if(t)
return t->m_facade;
@@ -755,15 +664,18 @@ void NdbDictionary::Dictionary::set_local_table_data_size(unsigned sz)
}
const NdbDictionary::Table *
-NdbDictionary::Dictionary::getTable(const char * name){
+NdbDictionary::Dictionary::getTable(const char * name) const
+{
return getTable(name, 0);
}
void
NdbDictionary::Dictionary::invalidateTable(const char * name){
+ DBUG_ENTER("NdbDictionaryImpl::invalidateTable");
NdbTableImpl * t = m_impl.getTable(name);
if(t)
m_impl.invalidateObject(* t);
+ DBUG_VOID_RETURN;
}
void
@@ -794,7 +706,7 @@ NdbDictionary::Dictionary::dropIndex(const Index & ind)
const NdbDictionary::Index *
NdbDictionary::Dictionary::getIndex(const char * indexName,
- const char * tableName)
+ const char * tableName) const
{
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
if(i)
@@ -804,7 +716,7 @@ NdbDictionary::Dictionary::getIndex(const char * indexName,
const NdbDictionary::Index *
NdbDictionary::Dictionary::getIndex(const char * indexName,
- const Table & t)
+ const Table & t) const
{
NdbIndexImpl * i = m_impl.getIndex(indexName, & NdbTableImpl::getImpl(t));
if(i)
@@ -815,11 +727,13 @@ NdbDictionary::Dictionary::getIndex(const char * indexName,
void
NdbDictionary::Dictionary::invalidateIndex(const char * indexName,
const char * tableName){
+ DBUG_ENTER("NdbDictionaryImpl::invalidateIndex");
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
if(i) {
assert(i->m_table != 0);
m_impl.invalidateObject(* i->m_table);
}
+ DBUG_VOID_RETURN;
}
void
@@ -834,7 +748,7 @@ NdbDictionary::Dictionary::removeCachedIndex(const char * indexName,
const NdbDictionary::Table *
NdbDictionary::Dictionary::getIndexTable(const char * indexName,
- const char * tableName)
+ const char * tableName) const
{
NdbIndexImpl * i = m_impl.getIndex(indexName, tableName);
NdbTableImpl * t = m_impl.getTable(tableName);
@@ -845,36 +759,32 @@ NdbDictionary::Dictionary::getIndexTable(const char * indexName,
return 0;
}
-
int
-NdbDictionary::Dictionary::createEvent(const Event & ev)
-{
- return m_impl.createEvent(NdbEventImpl::getImpl(ev));
-}
-
-int
-NdbDictionary::Dictionary::dropEvent(const char * eventName)
+NdbDictionary::Dictionary::listObjects(List& list, Object::Type type)
{
- return m_impl.dropEvent(eventName);
+ return m_impl.listObjects(list, type);
}
-const NdbDictionary::Event *
-NdbDictionary::Dictionary::getEvent(const char * eventName)
+int
+NdbDictionary::Dictionary::listObjects(List& list, Object::Type type) const
{
- NdbEventImpl * t = m_impl.getEvent(eventName);
- if(t)
- return t->m_facade;
- return 0;
+ return m_impl.listObjects(list, type);
}
int
-NdbDictionary::Dictionary::listObjects(List& list, Object::Type type)
+NdbDictionary::Dictionary::listIndexes(List& list, const char * tableName)
{
- return m_impl.listObjects(list, type);
+ const NdbDictionary::Table* tab= getTable(tableName);
+ if(tab == 0)
+ {
+ return -1;
+ }
+ return m_impl.listIndexes(list, tab->getTableId());
}
int
-NdbDictionary::Dictionary::listIndexes(List& list, const char * tableName)
+NdbDictionary::Dictionary::listIndexes(List& list,
+ const char * tableName) const
{
const NdbDictionary::Table* tab= getTable(tableName);
if(tab == 0)
@@ -940,6 +850,12 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
case NdbDictionary::Column::Olddecimalunsigned:
out << "Olddecimalunsigned(" << col.getPrecision() << "," << col.getScale() << ")";
break;
+ case NdbDictionary::Column::Decimal:
+ out << "Decimal(" << col.getPrecision() << "," << col.getScale() << ")";
+ break;
+ case NdbDictionary::Column::Decimalunsigned:
+ out << "Decimalunsigned(" << col.getPrecision() << "," << col.getScale() << ")";
+ break;
case NdbDictionary::Column::Char:
out << "Char(" << col.getLength() << ";" << csname << ")";
break;
@@ -978,10 +894,37 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
case NdbDictionary::Column::Undefined:
out << "Undefined";
break;
+ case NdbDictionary::Column::Bit:
+ out << "Bit(" << col.getLength() << ")";
+ break;
+ case NdbDictionary::Column::Longvarchar:
+ out << "Longvarchar(" << col.getLength() << ";" << csname << ")";
+ break;
+ case NdbDictionary::Column::Longvarbinary:
+ out << "Longvarbinary(" << col.getLength() << ")";
+ break;
default:
out << "Type" << (Uint32)col.getType();
break;
}
+ // show unusual (non-MySQL) array size
+ if (col.getLength() != 1) {
+ switch (col.getType()) {
+ case NdbDictionary::Column::Char:
+ case NdbDictionary::Column::Varchar:
+ case NdbDictionary::Column::Binary:
+ case NdbDictionary::Column::Varbinary:
+ case NdbDictionary::Column::Blob:
+ case NdbDictionary::Column::Text:
+ case NdbDictionary::Column::Bit:
+ case NdbDictionary::Column::Longvarchar:
+ case NdbDictionary::Column::Longvarbinary:
+ break;
+ default:
+ out << " [" << col.getLength() << "]";
+ break;
+ }
+ }
if (col.getPrimaryKey())
out << " PRIMARY KEY";
else if (! col.getNullable())
@@ -989,13 +932,15 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
else
out << " NULL";
- if (col.getDistributionKey())
+ if(col.getDistributionKey())
out << " DISTRIBUTION KEY";
-
+
return out;
}
const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_MEMORY = 0;
const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0;
const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0;
-
+const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0;
+const NdbDictionary::Column * NdbDictionary::Column::RANGE_NO = 0;
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index c2604ebe682..b91df24d8d7 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -32,8 +32,6 @@
#include <SimpleProperties.hpp>
#include <Bitmask.hpp>
#include <AttributeList.hpp>
-#include <NdbEventOperation.hpp>
-#include "NdbEventOperationImpl.hpp"
#include <NdbBlob.hpp>
#include "NdbBlobImpl.hpp"
#include <AttributeHeader.hpp>
@@ -70,16 +68,11 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
m_scale = col.m_scale;
m_length = col.m_length;
m_pk = col.m_pk;
- m_tupleKey = col.m_tupleKey;
m_distributionKey = col.m_distributionKey;
- m_distributionGroup = col.m_distributionGroup;
- m_distributionGroupBits = col.m_distributionGroupBits;
m_nullable = col.m_nullable;
- m_indexOnly = col.m_indexOnly;
m_autoIncrement = col.m_autoIncrement;
m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
m_defaultValue = col.m_defaultValue;
- m_attrType = col.m_attrType;
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
m_keyInfoPos = col.m_keyInfoPos;
@@ -116,6 +109,8 @@ NdbColumnImpl::init(Type t)
break;
case Olddecimal:
case Olddecimalunsigned:
+ case Decimal:
+ case Decimalunsigned:
m_precision = 10;
m_scale = 0;
m_length = 1;
@@ -157,17 +152,32 @@ NdbColumnImpl::init(Type t)
m_length = 1;
m_cs = NULL;
break;
+ case Bit:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = NULL;
+ break;
+ case Longvarchar:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1; // legal
+ m_cs = default_cs;
+ break;
+ case Longvarbinary:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1; // legal
+ m_cs = NULL;
+ break;
+ default:
case Undefined:
assert(false);
break;
}
m_pk = false;
m_nullable = false;
- m_tupleKey = false;
- m_indexOnly = false;
m_distributionKey = false;
- m_distributionGroup = false;
- m_distributionGroupBits = 8;
m_keyInfoPos = 0;
// next 2 are set at run time
m_attrSize = 0;
@@ -184,50 +194,40 @@ NdbColumnImpl::~NdbColumnImpl()
bool
NdbColumnImpl::equal(const NdbColumnImpl& col) const
{
+ DBUG_ENTER("NdbColumnImpl::equal");
if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
- return false;
+ DBUG_RETURN(false);
}
if(m_type != col.m_type){
- return false;
+ DBUG_RETURN(false);
}
if(m_pk != col.m_pk){
- return false;
+ DBUG_RETURN(false);
}
if(m_nullable != col.m_nullable){
- return false;
+ DBUG_RETURN(false);
}
+#ifdef ndb_dictionary_dkey_fixed
if(m_pk){
- if(m_tupleKey != col.m_tupleKey){
- return false;
- }
- if(m_indexOnly != col.m_indexOnly){
- return false;
- }
if(m_distributionKey != col.m_distributionKey){
- return false;
- }
- if(m_distributionGroup != col.m_distributionGroup){
- return false;
- }
- if(m_distributionGroup &&
- (m_distributionGroupBits != col.m_distributionGroupBits)){
- return false;
+ DBUG_RETURN(false);
}
}
+#endif
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
m_length != col.m_length ||
m_cs != col.m_cs) {
- return false;
+ DBUG_RETURN(false);
}
if (m_autoIncrement != col.m_autoIncrement){
- return false;
+ DBUG_RETURN(false);
}
if(strcmp(m_defaultValue.c_str(), col.m_defaultValue.c_str()) != 0){
- return false;
+ DBUG_RETURN(false);
}
- return true;
+ DBUG_RETURN(true);
}
NdbDictionary::Column *
@@ -239,6 +239,11 @@ NdbColumnImpl::create_psuedo(const char * name){
col->m_impl.m_attrId = AttributeHeader::FRAGMENT;
col->m_impl.m_attrSize = 4;
col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$FRAGMENT_MEMORY")){
+ col->setType(NdbDictionary::Column::Bigunsigned);
+ col->m_impl.m_attrId = AttributeHeader::FRAGMENT_MEMORY;
+ col->m_impl.m_attrSize = 8;
+ col->m_impl.m_arraySize = 1;
} else if(!strcmp(name, "NDB$ROW_COUNT")){
col->setType(NdbDictionary::Column::Bigunsigned);
col->m_impl.m_attrId = AttributeHeader::ROW_COUNT;
@@ -249,6 +254,16 @@ NdbColumnImpl::create_psuedo(const char * name){
col->m_impl.m_attrId = AttributeHeader::COMMIT_COUNT;
col->m_impl.m_attrSize = 8;
col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$ROW_SIZE")){
+ col->setType(NdbDictionary::Column::Unsigned);
+ col->m_impl.m_attrId = AttributeHeader::ROW_SIZE;
+ col->m_impl.m_attrSize = 4;
+ col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$RANGE_NO")){
+ col->setType(NdbDictionary::Column::Unsigned);
+ col->m_impl.m_attrId = AttributeHeader::RANGE_NO;
+ col->m_impl.m_attrSize = 4;
+ col->m_impl.m_arraySize = 1;
} else {
abort();
}
@@ -283,69 +298,88 @@ NdbTableImpl::~NdbTableImpl()
void
NdbTableImpl::init(){
- clearNewProperties();
+ m_changeMask= 0;
+ m_tableId= RNIL;
m_frm.clear();
- m_fragmentType = NdbDictionary::Object::FragAllSmall;
- m_logging = true;
- m_kvalue = 6;
- m_minLoadFactor = 78;
- m_maxLoadFactor = 80;
-
- m_index = 0;
- m_indexType = NdbDictionary::Index::Undefined;
-
- m_noOfKeys = 0;
- m_fragmentCount = 0;
- m_sizeOfKeysInWords = 0;
- m_noOfBlobs = 0;
+ m_fragmentType= NdbDictionary::Object::FragAllSmall;
+ m_hashValueMask= 0;
+ m_hashpointerValue= 0;
+ m_logging= true;
+ m_kvalue= 6;
+ m_minLoadFactor= 78;
+ m_maxLoadFactor= 80;
+ m_keyLenInWords= 0;
+ m_fragmentCount= 0;
+ m_dictionary= NULL;
+ m_index= NULL;
+ m_indexType= NdbDictionary::Index::Undefined;
+ m_noOfKeys= 0;
+ m_noOfDistributionKeys= 0;
+ m_noOfBlobs= 0;
+ m_replicaCount= 0;
+ m_min_rows = 0;
+ m_max_rows = 0;
}
bool
NdbTableImpl::equal(const NdbTableImpl& obj) const
{
+ DBUG_ENTER("NdbTableImpl::equal");
if ((m_internalName.c_str() == NULL) ||
(strcmp(m_internalName.c_str(), "") == 0) ||
(obj.m_internalName.c_str() == NULL) ||
(strcmp(obj.m_internalName.c_str(), "") == 0)) {
// Shallow equal
if(strcmp(getName(), obj.getName()) != 0){
- return false;
+ DBUG_PRINT("info",("name %s != %s",getName(),obj.getName()));
+ DBUG_RETURN(false);
}
} else
// Deep equal
if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){
- return false;
+ {
+ DBUG_PRINT("info",("m_internalName %s != %s",
+ m_internalName.c_str(),obj.m_internalName.c_str()));
+ DBUG_RETURN(false);
+ }
}
if(m_fragmentType != obj.m_fragmentType){
- return false;
+ DBUG_PRINT("info",("m_fragmentType %d != %d",m_fragmentType,obj.m_fragmentType));
+ DBUG_RETURN(false);
}
if(m_columns.size() != obj.m_columns.size()){
- return false;
+ DBUG_PRINT("info",("m_columns.size %d != %d",m_columns.size(),obj.m_columns.size()));
+ DBUG_RETURN(false);
}
for(unsigned i = 0; i<obj.m_columns.size(); i++){
if(!m_columns[i]->equal(* obj.m_columns[i])){
- return false;
+ DBUG_PRINT("info",("m_columns [%d] != [%d]",i,i));
+ DBUG_RETURN(false);
}
}
if(m_logging != obj.m_logging){
- return false;
+ DBUG_PRINT("info",("m_logging %d != %d",m_logging,obj.m_logging));
+ DBUG_RETURN(false);
}
if(m_kvalue != obj.m_kvalue){
- return false;
+ DBUG_PRINT("info",("m_kvalue %d != %d",m_kvalue,obj.m_kvalue));
+ DBUG_RETURN(false);
}
if(m_minLoadFactor != obj.m_minLoadFactor){
- return false;
+ DBUG_PRINT("info",("m_minLoadFactor %d != %d",m_minLoadFactor,obj.m_minLoadFactor));
+ DBUG_RETURN(false);
}
if(m_maxLoadFactor != obj.m_maxLoadFactor){
- return false;
+ DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,obj.m_maxLoadFactor));
+ DBUG_RETURN(false);
}
- return true;
+ DBUG_RETURN(true);
}
void
@@ -375,12 +409,16 @@ NdbTableImpl::assign(const NdbTableImpl& org)
delete m_index;
m_index = org.m_index;
+ m_noOfDistributionKeys = org.m_noOfDistributionKeys;
m_noOfKeys = org.m_noOfKeys;
- m_sizeOfKeysInWords = org.m_sizeOfKeysInWords;
+ m_keyLenInWords = org.m_keyLenInWords;
m_noOfBlobs = org.m_noOfBlobs;
m_version = org.m_version;
m_status = org.m_status;
+
+ m_max_rows = org.m_max_rows;
+ m_min_rows = org.m_min_rows;
}
void NdbTableImpl::setName(const char * name)
@@ -397,19 +435,6 @@ NdbTableImpl::getName() const
return m_newExternalName.c_str();
}
-void NdbTableImpl::clearNewProperties()
-{
- m_newExternalName.assign("");
- m_changeMask = 0;
-}
-
-void NdbTableImpl::copyNewProperties()
-{
- if (!m_newExternalName.empty()) {
- m_externalName.assign(m_newExternalName);
- AlterTableReq::setNameFlag(m_changeMask, true);
- }
-}
void
NdbTableImpl::buildColumnHash(){
@@ -477,6 +502,26 @@ NdbTableImpl::buildColumnHash(){
}
#endif
}
+
+Uint32
+NdbTableImpl::get_nodes(Uint32 hashValue, const Uint16 ** nodes) const
+{
+ if(m_replicaCount > 0)
+ {
+ Uint32 fragmentId = hashValue & m_hashValueMask;
+ if(fragmentId < m_hashpointerValue)
+ {
+ fragmentId = hashValue & ((m_hashValueMask << 1) + 1);
+ }
+ Uint32 pos = fragmentId * m_replicaCount;
+ if(pos + m_replicaCount <= m_fragments.size())
+ {
+ * nodes = m_fragments.getBase()+pos;
+ return m_replicaCount;
+ }
+ }
+ return 0;
+}
/**
* NdbIndexImpl
@@ -486,14 +531,22 @@ NdbIndexImpl::NdbIndexImpl() :
NdbDictionary::Index(* this),
m_facade(this)
{
- m_logging = true;
+ init();
}
NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
NdbDictionary::Index(* this),
m_facade(&f)
{
- m_logging = true;
+ init();
+}
+
+void NdbIndexImpl::init()
+{
+ m_indexId= RNIL;
+ m_type= NdbDictionary::Index::Undefined;
+ m_logging= true;
+ m_table= NULL;
}
NdbIndexImpl::~NdbIndexImpl(){
@@ -531,76 +584,6 @@ NdbIndexImpl::getIndexTable() const
}
/**
- * NdbEventImpl
- */
-
-NdbEventImpl::NdbEventImpl() :
- NdbDictionary::Event(* this),
- m_facade(this)
-{
- mi_type = 0;
- m_dur = NdbDictionary::Event::ED_UNDEFINED;
- eventOp = NULL;
- m_tableImpl = NULL;
-}
-
-NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
- NdbDictionary::Event(* this),
- m_facade(&f)
-{
- mi_type = 0;
- m_dur = NdbDictionary::Event::ED_UNDEFINED;
- eventOp = NULL;
- m_tableImpl = NULL;
-}
-
-NdbEventImpl::~NdbEventImpl()
-{
- for (unsigned i = 0; i < m_columns.size(); i++)
- delete m_columns[i];
-}
-
-void NdbEventImpl::setName(const char * name)
-{
- m_externalName.assign(name);
-}
-
-void
-NdbEventImpl::setTable(const char * table)
-{
- m_tableName.assign(table);
-}
-
-const char *
-NdbEventImpl::getTable() const
-{
- return m_tableName.c_str();
-}
-
-const char *
-NdbEventImpl::getName() const
-{
- return m_externalName.c_str();
-}
-
-void
-NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t = NdbDictionary::Event::TE_ALL)
-{
- switch (t) {
- case NdbDictionary::Event::TE_INSERT : mi_type |= 1; break;
- case NdbDictionary::Event::TE_DELETE : mi_type |= 2; break;
- case NdbDictionary::Event::TE_UPDATE : mi_type |= 4; break;
- default: mi_type = 4 | 2 | 1; // all types
- }
-}
-
-void
-NdbEventImpl::setDurability(const NdbDictionary::Event::EventDurability d)
-{
- m_dur = d;
-}
-
-/**
* NdbDictionaryImpl
*/
@@ -643,11 +626,17 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
m_globalHash->lock();
if(--f_dictionary_count == 0){
delete NdbDictionary::Column::FRAGMENT;
+ delete NdbDictionary::Column::FRAGMENT_MEMORY;
delete NdbDictionary::Column::ROW_COUNT;
delete NdbDictionary::Column::COMMIT_COUNT;
+ delete NdbDictionary::Column::ROW_SIZE;
+ delete NdbDictionary::Column::RANGE_NO;
NdbDictionary::Column::FRAGMENT= 0;
+ NdbDictionary::Column::FRAGMENT_MEMORY= 0;
NdbDictionary::Column::ROW_COUNT= 0;
NdbDictionary::Column::COMMIT_COUNT= 0;
+ NdbDictionary::Column::ROW_SIZE= 0;
+ NdbDictionary::Column::RANGE_NO= 0;
}
m_globalHash->unlock();
} else {
@@ -656,19 +645,19 @@ NdbDictionaryImpl::~NdbDictionaryImpl()
}
Ndb_local_table_info *
-NdbDictionaryImpl::fetchGlobalTableImpl(const char * internalTableName)
+NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName)
{
NdbTableImpl *impl;
m_globalHash->lock();
- impl = m_globalHash->get(internalTableName);
+ impl = m_globalHash->get(internalTableName.c_str());
m_globalHash->unlock();
if (impl == 0){
impl = m_receiver.getTable(internalTableName,
m_ndb.usingFullyQualifiedNames());
m_globalHash->lock();
- m_globalHash->put(internalTableName, impl);
+ m_globalHash->put(internalTableName.c_str(), impl);
m_globalHash->unlock();
if(impl == 0){
@@ -679,11 +668,7 @@ NdbDictionaryImpl::fetchGlobalTableImpl(const char * internalTableName)
Ndb_local_table_info *info=
Ndb_local_table_info::create(impl, m_local_table_data_size);
- m_localHash.put(internalTableName, info);
-
- m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
- m_ndb.theLastTupleId[impl->getTableId()] = ~0;
-
+ m_localHash.put(internalTableName.c_str(), info);
return info;
}
@@ -710,10 +695,16 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb,
if(f_dictionary_count++ == 0){
NdbDictionary::Column::FRAGMENT=
NdbColumnImpl::create_psuedo("NDB$FRAGMENT");
+ NdbDictionary::Column::FRAGMENT_MEMORY=
+ NdbColumnImpl::create_psuedo("NDB$FRAGMENT_MEMORY");
NdbDictionary::Column::ROW_COUNT=
NdbColumnImpl::create_psuedo("NDB$ROW_COUNT");
NdbDictionary::Column::COMMIT_COUNT=
NdbColumnImpl::create_psuedo("NDB$COMMIT_COUNT");
+ NdbDictionary::Column::ROW_SIZE=
+ NdbColumnImpl::create_psuedo("NDB$ROW_SIZE");
+ NdbDictionary::Column::RANGE_NO=
+ NdbColumnImpl::create_psuedo("NDB$RANGE_NO");
}
m_globalHash->unlock();
return true;
@@ -721,14 +712,13 @@ NdbDictionaryImpl::setTransporter(class Ndb* ndb,
return false;
}
-NdbTableImpl *
-NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
+NdbTableImpl *
+NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
NdbTableImpl * table)
{
- const char * internalName =
- m_ndb.internalizeIndexName(table, index->getName());
-
- return getTable(m_ndb.externalizeTableName(internalName));
+ const BaseString internalName(
+ m_ndb.internalize_index_name(table, index->getName()));
+ return getTable(m_ndb.externalizeTableName(internalName.c_str()));
}
#if 0
@@ -745,7 +735,7 @@ NdbDictInterface::setTransporter(class TransporterFacade * tf)
execNodeStatus);
if ( m_blockNumber == -1 ) {
- m_error.code = 4105;
+ m_error.code= 4105;
return false; // no more free blocknumbers
}//if
Uint32 theNode = tf->ownId();
@@ -816,36 +806,6 @@ NdbDictInterface::execSignal(void* dictImpl,
case GSN_DROP_INDX_CONF:
tmp->execDROP_INDX_CONF(signal, ptr);
break;
- case GSN_CREATE_EVNT_REF:
- tmp->execCREATE_EVNT_REF(signal, ptr);
- break;
- case GSN_CREATE_EVNT_CONF:
- tmp->execCREATE_EVNT_CONF(signal, ptr);
- break;
- case GSN_SUB_START_CONF:
- tmp->execSUB_START_CONF(signal, ptr);
- break;
- case GSN_SUB_START_REF:
- tmp->execSUB_START_REF(signal, ptr);
- break;
- case GSN_SUB_TABLE_DATA:
- tmp->execSUB_TABLE_DATA(signal, ptr);
- break;
- case GSN_SUB_GCP_COMPLETE_REP:
- tmp->execSUB_GCP_COMPLETE_REP(signal, ptr);
- break;
- case GSN_SUB_STOP_CONF:
- tmp->execSUB_STOP_CONF(signal, ptr);
- break;
- case GSN_SUB_STOP_REF:
- tmp->execSUB_STOP_REF(signal, ptr);
- break;
- case GSN_DROP_EVNT_REF:
- tmp->execDROP_EVNT_REF(signal, ptr);
- break;
- case GSN_DROP_EVNT_CONF:
- tmp->execDROP_EVNT_CONF(signal, ptr);
- break;
case GSN_LIST_TABLES_CONF:
tmp->execLIST_TABLES_CONF(signal, ptr);
break;
@@ -899,7 +859,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
aNodeId = m_transporter->get_an_alive_node();
}
if(aNodeId == 0){
- m_error.code = 4009;
+ m_error.code= 4009;
m_transporter->unlock_mutex();
DBUG_RETURN(-1);
}
@@ -926,7 +886,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
}
}
- m_error.code = 0;
+ m_error.code= 0;
m_waiter.m_node = aNodeId;
m_waiter.m_state = wst;
@@ -960,7 +920,7 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
for (int j=0; j < noerrcodes; j++)
if(m_error.code == errcodes[j]) {
doContinue = 1;
- continue;
+ break;
}
if (doContinue)
continue;
@@ -970,80 +930,98 @@ NdbDictInterface::dictSignal(NdbApiSignal* signal,
}
DBUG_RETURN(-1);
}
+#if 0
+/*
+ Get dictionary information for a table using table id as reference
-/*****************************************************************
- * get tab info
+ DESCRIPTION
+ Sends a GET_TABINFOREQ signal containing the table id
*/
-NdbTableImpl *
+NdbTableImpl *
NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
- GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
-
+ GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
req->senderRef = m_reference;
req->senderData = 0;
- req->requestType =
+ req->requestType =
GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
req->tableId = tableId;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
tSignal.theLength = GetTabInfoReq::SignalLength;
-
+
return getTable(&tSignal, 0, 0, fullyQualifiedNames);
}
+#endif
+
+
+/*
+ Get dictionary information for a table using table name as the reference
+
+ DESCRIPTION
+ Send GET_TABINFOREQ signal with the table name in the first
+ long section part
+*/
-NdbTableImpl *
-NdbDictInterface::getTable(const char * name, bool fullyQualifiedNames)
+NdbTableImpl *
+NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
- GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
-
- const Uint32 strLen = strlen(name) + 1; // NULL Terminated
- if(strLen > MAX_TAB_NAME_SIZE) {//sizeof(req->tableName)){
- m_error.code = 4307;
- return 0;
- }
+ GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
- // avoid alignment problem and memory overrun
- Uint32 name_buf[(MAX_TAB_NAME_SIZE + 3) / 4];
- strncpy((char*)name_buf, name, sizeof(name_buf)); // strncpy null-pads
- name = (char*)name_buf;
+ const Uint32 namelen= name.length() + 1; // NULL terminated
+ const Uint32 namelen_words= (namelen + 3) >> 2; // Size in words
- req->senderRef = m_reference;
- req->senderData = 0;
- req->requestType =
+ req->senderRef= m_reference;
+ req->senderData= 0;
+ req->requestType=
GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
- req->tableNameLen = strLen;
- tSignal.theReceiversBlockNumber = DBDICT;
- tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
- // tSignal.theLength = GetTabInfoReq::HeaderLength + ((strLen + 3) / 4);
- tSignal.theLength = GetTabInfoReq::SignalLength;
- LinearSectionPtr ptr[1];
- ptr[0].p = (Uint32*)name;
- ptr[0].sz = (strLen + 3) / 4;
+ req->tableNameLen= namelen;
+ tSignal.theReceiversBlockNumber= DBDICT;
+ tSignal.theVerId_signalNumber= GSN_GET_TABINFOREQ;
+ tSignal.theLength= GetTabInfoReq::SignalLength;
+
+ // Copy name to m_buffer to get a word sized buffer
+ m_buffer.clear();
+ m_buffer.grow(namelen_words*4+4);
+ m_buffer.append(name.c_str(), namelen);
+
+#ifndef IGNORE_VALGRIND_WARNINGS
+ Uint32 pad = 0;
+ m_buffer.append(&pad, 4);
+#endif
+ LinearSectionPtr ptr[1];
+ ptr[0].p= (Uint32*)m_buffer.get_data();
+ ptr[0].sz= namelen_words;
+
return getTable(&tSignal, ptr, 1, fullyQualifiedNames);
}
+
NdbTableImpl *
-NdbDictInterface::getTable(class NdbApiSignal * signal,
+NdbDictInterface::getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames)
{
- //GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, signal->getDataPtrSend());
+ int errCodes[] = {GetTabInfoRef::Busy };
+
int r = dictSignal(signal,ptr,noOfSections,
0/*do not use masternode id*/,
100,
WAIT_GET_TAB_INFO_REQ,
WAITFOR_RESPONSE_TIMEOUT,
- NULL,0);
+ errCodes, 1);
if (r) return 0;
NdbTableImpl * rt = 0;
- m_error.code = parseTableInfo(&rt,
- (Uint32*)m_buffer.get_data(),
- m_buffer.length() / 4, fullyQualifiedNames);
- rt->buildColumnHash();
+ m_error.code= parseTableInfo(&rt,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4, fullyQualifiedNames);
+ if (rt != 0)
+ rt->buildColumnHash();
return rt;
}
@@ -1077,7 +1055,7 @@ NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
{
const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_waiter.signal(NO_WAIT);
}
@@ -1133,8 +1111,6 @@ objectTypeMapping[] = {
{ DictTabInfo::SystemTable, NdbDictionary::Object::SystemTable },
{ DictTabInfo::UserTable, NdbDictionary::Object::UserTable },
{ DictTabInfo::UniqueHashIndex, NdbDictionary::Object::UniqueHashIndex },
- { DictTabInfo::HashIndex, NdbDictionary::Object::HashIndex },
- { DictTabInfo::UniqueOrderedIndex, NdbDictionary::Object::UniqueOrderedIndex },
{ DictTabInfo::OrderedIndex, NdbDictionary::Object::OrderedIndex },
{ DictTabInfo::HashIndexTrigger, NdbDictionary::Object::HashIndexTrigger },
{ DictTabInfo::IndexTrigger, NdbDictionary::Object::IndexTrigger },
@@ -1167,49 +1143,17 @@ static const
ApiKernelMapping
indexTypeMapping[] = {
{ DictTabInfo::UniqueHashIndex, NdbDictionary::Index::UniqueHashIndex },
- { DictTabInfo::HashIndex, NdbDictionary::Index::HashIndex },
- { DictTabInfo::UniqueOrderedIndex, NdbDictionary::Index::UniqueOrderedIndex},
{ DictTabInfo::OrderedIndex, NdbDictionary::Index::OrderedIndex },
{ -1, -1 }
};
-// TODO: remove, api-kernel type codes must match now
-static const
-ApiKernelMapping
-columnTypeMapping[] = {
- { DictTabInfo::ExtTinyint, NdbDictionary::Column::Tinyint },
- { DictTabInfo::ExtTinyunsigned, NdbDictionary::Column::Tinyunsigned },
- { DictTabInfo::ExtSmallint, NdbDictionary::Column::Smallint },
- { DictTabInfo::ExtSmallunsigned, NdbDictionary::Column::Smallunsigned },
- { DictTabInfo::ExtMediumint, NdbDictionary::Column::Mediumint },
- { DictTabInfo::ExtMediumunsigned, NdbDictionary::Column::Mediumunsigned },
- { DictTabInfo::ExtInt, NdbDictionary::Column::Int },
- { DictTabInfo::ExtUnsigned, NdbDictionary::Column::Unsigned },
- { DictTabInfo::ExtBigint, NdbDictionary::Column::Bigint },
- { DictTabInfo::ExtBigunsigned, NdbDictionary::Column::Bigunsigned },
- { DictTabInfo::ExtFloat, NdbDictionary::Column::Float },
- { DictTabInfo::ExtDouble, NdbDictionary::Column::Double },
- { DictTabInfo::ExtOlddecimal, NdbDictionary::Column::Olddecimal },
- { DictTabInfo::ExtOlddecimalunsigned, NdbDictionary::Column::Olddecimalunsigned },
- { DictTabInfo::ExtChar, NdbDictionary::Column::Char },
- { DictTabInfo::ExtVarchar, NdbDictionary::Column::Varchar },
- { DictTabInfo::ExtBinary, NdbDictionary::Column::Binary },
- { DictTabInfo::ExtVarbinary, NdbDictionary::Column::Varbinary },
- { DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime },
- { DictTabInfo::ExtDate, NdbDictionary::Column::Date },
- { DictTabInfo::ExtBlob, NdbDictionary::Column::Blob },
- { DictTabInfo::ExtText, NdbDictionary::Column::Text },
- { DictTabInfo::ExtTime, NdbDictionary::Column::Time },
- { DictTabInfo::ExtYear, NdbDictionary::Column::Year },
- { DictTabInfo::ExtTimestamp, NdbDictionary::Column::Timestamp },
- { -1, -1 }
-};
-
int
NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
const Uint32 * data, Uint32 len,
bool fullyQualifiedNames)
{
+ DBUG_ENTER("NdbDictInterface::parseTableInfo");
+
SimplePropertiesLinearReader it(data, len);
DictTabInfo::Table tableDesc; tableDesc.init();
SimpleProperties::UnpackStatus s;
@@ -1219,7 +1163,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
true, true);
if(s != SimpleProperties::Break){
- return 703;
+ DBUG_RETURN(703);
}
const char * internalName = tableDesc.TableName;
const char * externalName = Ndb::externalizeTableName(internalName, fullyQualifiedNames);
@@ -1238,11 +1182,16 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
fragmentTypeMapping,
(Uint32)NdbDictionary::Object::FragUndefined);
+ Uint64 max_rows = ((Uint64)tableDesc.MaxRowsHigh) << 32;
+ max_rows += tableDesc.MaxRowsLow;
+ impl->m_max_rows = max_rows;
+ Uint64 min_rows = ((Uint64)tableDesc.MinRowsHigh) << 32;
+ min_rows += tableDesc.MinRowsLow;
+ impl->m_min_rows = min_rows;
impl->m_logging = tableDesc.TableLoggedFlag;
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,
@@ -1259,8 +1208,10 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
Uint32 keyInfoPos = 0;
Uint32 keyCount = 0;
Uint32 blobCount = 0;
+ Uint32 distKeys = 0;
- for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
+ Uint32 i;
+ for(i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
s = SimpleProperties::unpack(it,
&attrDesc,
@@ -1269,21 +1220,19 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
true, true);
if(s != SimpleProperties::Break){
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
NdbColumnImpl * col = new NdbColumnImpl();
col->m_attrId = attrDesc.AttributeId;
col->setName(attrDesc.AttributeName);
- col->m_type = (NdbDictionary::Column::Type)
- getApiConstant(attrDesc.AttributeExtType,
- columnTypeMapping,
- NdbDictionary::Column::Undefined);
- if (col->m_type == NdbDictionary::Column::Undefined) {
+
+ // check type and compute attribute size and array size
+ if (! attrDesc.translateExtType()) {
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
- col->m_extType = attrDesc.AttributeExtType;
+ col->m_type = (NdbDictionary::Column::Type)attrDesc.AttributeExtType;
col->m_precision = (attrDesc.AttributeExtPrecision & 0xFFFF);
col->m_scale = attrDesc.AttributeExtScale;
col->m_length = attrDesc.AttributeExtLength;
@@ -1292,32 +1241,26 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
// charset is defined exactly for char types
if (col->getCharType() != (cs_number != 0)) {
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
if (col->getCharType()) {
col->m_cs = get_charset(cs_number, MYF(0));
if (col->m_cs == NULL) {
delete impl;
- return 743;
+ DBUG_RETURN(743);
}
}
-
- // translate to old kernel types and sizes
- if (! attrDesc.translateExtType()) {
- delete impl;
- return 703;
- }
- col->m_attrType =attrDesc.AttributeType;
col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
col->m_arraySize = attrDesc.AttributeArraySize;
+ if(attrDesc.AttributeSize == 0)
+ {
+ col->m_attrSize = 4;
+ col->m_arraySize = (attrDesc.AttributeArraySize + 31) >> 5;
+ }
col->m_pk = attrDesc.AttributeKeyFlag;
- col->m_tupleKey = 0;
col->m_distributionKey = attrDesc.AttributeDKey;
- col->m_distributionGroup = attrDesc.AttributeDGroup;
- col->m_distributionGroupBits = 16;
col->m_nullable = attrDesc.AttributeNullableFlag;
- col->m_indexOnly = (attrDesc.AttributeStoredInd ? false : true);
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
col->m_autoIncrementInitialValue = ~0;
col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
@@ -1326,6 +1269,9 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
col->m_keyInfoPos = keyInfoPos + 1;
keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
keyCount++;
+
+ if(attrDesc.AttributeDKey)
+ distKeys++;
} else {
col->m_keyInfoPos = 0;
}
@@ -1336,7 +1282,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
if(impl->m_columns[attrDesc.AttributeId] != 0){
delete col;
delete impl;
- return 703;
+ DBUG_RETURN(703);
}
impl->m_columns[attrDesc.AttributeId] = col;
it.next();
@@ -1344,10 +1290,49 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_noOfKeys = keyCount;
impl->m_keyLenInWords = keyInfoPos;
- impl->m_sizeOfKeysInWords = keyInfoPos;
impl->m_noOfBlobs = blobCount;
+ impl->m_noOfDistributionKeys = distKeys;
+
+ if(tableDesc.FragmentDataLen > 0)
+ {
+ Uint32 replicaCount = tableDesc.FragmentData[0];
+ Uint32 fragCount = tableDesc.FragmentData[1];
+
+ impl->m_replicaCount = replicaCount;
+ impl->m_fragmentCount = fragCount;
+
+ for(i = 0; i<(fragCount*replicaCount); i++)
+ {
+ impl->m_fragments.push_back(tableDesc.FragmentData[i+2]);
+ }
+
+ Uint32 topBit = (1 << 31);
+ for(; topBit && !(fragCount & topBit); ){
+ topBit >>= 1;
+ }
+ impl->m_hashValueMask = topBit - 1;
+ impl->m_hashpointerValue = fragCount - (impl->m_hashValueMask + 1);
+ }
+ else
+ {
+ impl->m_fragmentCount = tableDesc.FragmentCount;
+ impl->m_replicaCount = 0;
+ impl->m_hashValueMask = 0;
+ impl->m_hashpointerValue = 0;
+ }
+
+ if(distKeys == 0)
+ {
+ for(i = 0; i < tableDesc.NoOfAttributes; i++)
+ {
+ if(impl->m_columns[i]->getPrimaryKey())
+ impl->m_columns[i]->m_distributionKey = true;
+ }
+ }
+
* ret = impl;
- return 0;
+
+ DBUG_RETURN(0);
}
/*****************************************************************
@@ -1362,15 +1347,15 @@ NdbDictionaryImpl::createTable(NdbTableImpl &t)
return 0;
// update table def from DICT
Ndb_local_table_info *info=
- get_local_table_info(t.m_internalName.c_str(),false);
+ get_local_table_info(t.m_internalName,false);
if (info == NULL) {
- m_error.code = 709;
+ m_error.code= 709;
return -1;
}
if (createBlobTables(*(info->m_table_impl)) != 0) {
int save_code = m_error.code;
(void)dropTable(t);
- m_error.code = save_code;
+ m_error.code= save_code;
return -1;
}
return 0;
@@ -1389,7 +1374,7 @@ NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
return -1;
// Save BLOB table handle
Ndb_local_table_info *info=
- get_local_table_info(bt.m_internalName.c_str(),false);
+ get_local_table_info(bt.m_internalName, false);
if (info == 0) {
return -1;
}
@@ -1433,10 +1418,8 @@ NdbDictInterface::createTable(Ndb & ndb,
int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
{
- BaseString internalName = impl.m_internalName;
+ BaseString internalName(impl.m_internalName);
const char * originalInternalName = internalName.c_str();
- BaseString externalName = impl.m_externalName;
- const char * originalExternalName = externalName.c_str();
DBUG_ENTER("NdbDictionaryImpl::alterTable");
Ndb_local_table_info * local = 0;
@@ -1472,49 +1455,56 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
bool alter)
{
DBUG_ENTER("NdbDictInterface::createOrAlterTable");
- unsigned i;
+ unsigned i, err;
if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
- m_error.code = 4317;
+ m_error.code= 4317;
DBUG_RETURN(-1);
}
unsigned sz = impl.m_columns.size();
if (sz > NDB_MAX_ATTRIBUTES_IN_TABLE){
- m_error.code = 4318;
+ m_error.code= 4318;
DBUG_RETURN(-1);
}
- impl.copyNewProperties();
+ if (!impl.m_newExternalName.empty()) {
+ impl.m_externalName.assign(impl.m_newExternalName);
+ AlterTableReq::setNameFlag(impl.m_changeMask, true);
+ }
+
//validate();
//aggregate();
- const char * internalName =
- ndb.internalizeTableName(impl.m_externalName.c_str());
+ const BaseString internalName(
+ ndb.internalize_table_name(impl.m_externalName.c_str()));
impl.m_internalName.assign(internalName);
UtilBufferWriter w(m_buffer);
DictTabInfo::Table tmpTab; tmpTab.init();
- BaseString::snprintf(tmpTab.TableName,
- sizeof(tmpTab.TableName),
- internalName);
+ BaseString::snprintf(tmpTab.TableName,
+ sizeof(tmpTab.TableName),
+ internalName.c_str());
bool haveAutoIncrement = false;
Uint64 autoIncrementValue = 0;
+ Uint32 distKeys= 0;
for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
continue;
if (col->m_autoIncrement) {
if (haveAutoIncrement) {
- m_error.code = 4335;
+ m_error.code= 4335;
DBUG_RETURN(-1);
}
haveAutoIncrement = true;
autoIncrementValue = col->m_autoIncrementInitialValue;
- }
+ }
+ if (col->m_distributionKey)
+ distKeys++;
}
// Check max length of frm data
if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
- m_error.code = 1229;
+ m_error.code= 1229;
DBUG_RETURN(-1);
}
tmpTab.FrmLen = impl.m_frm.length();
@@ -1526,7 +1516,16 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
tmpTab.MaxLoadFactor = impl.m_maxLoadFactor;
tmpTab.TableType = DictTabInfo::UserTable;
tmpTab.NoOfAttributes = sz;
+ tmpTab.MaxRowsHigh = (Uint32)(impl.m_max_rows >> 32);
+ tmpTab.MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF);
+ tmpTab.MinRowsHigh = (Uint32)(impl.m_min_rows >> 32);
+ tmpTab.MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
+ Uint64 maxRows =
+ (((Uint64)tmpTab.MaxRowsHigh) << 32) + tmpTab.MaxRowsLow;
+ Uint64 minRows =
+ (((Uint64)tmpTab.MinRowsHigh) << 32) + tmpTab.MinRowsLow;
+
tmpTab.FragmentType = getKernelConstant(impl.m_fragmentType,
fragmentTypeMapping,
DictTabInfo::AllNodesSmallTable);
@@ -1542,6 +1541,10 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
abort();
}
+ if (distKeys == impl.m_noOfKeys)
+ distKeys= 0;
+ impl.m_noOfDistributionKeys= distKeys;
+
for(i = 0; i<sz; i++){
const NdbColumnImpl * col = impl.m_columns[i];
if(col == 0)
@@ -1551,27 +1554,35 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
tmpAttr.AttributeId = i;
- tmpAttr.AttributeKeyFlag = col->m_pk || col->m_tupleKey;
+ tmpAttr.AttributeKeyFlag = col->m_pk;
tmpAttr.AttributeNullableFlag = col->m_nullable;
- tmpAttr.AttributeStoredInd = (col->m_indexOnly ? 0 : 1);
- tmpAttr.AttributeDKey = col->m_distributionKey;
- tmpAttr.AttributeDGroup = col->m_distributionGroup;
-
- tmpAttr.AttributeExtType =
- getKernelConstant(col->m_type,
- columnTypeMapping,
- DictTabInfo::ExtUndefined);
+ tmpAttr.AttributeDKey = distKeys ? col->m_distributionKey : 0;
+
+ tmpAttr.AttributeExtType = (Uint32)col->m_type;
tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
tmpAttr.AttributeExtScale = col->m_scale;
tmpAttr.AttributeExtLength = col->m_length;
+
+ // check type and compute attribute size and array size
+ if (! tmpAttr.translateExtType()) {
+ m_error.code= 703;
+ DBUG_RETURN(-1);
+ }
// charset is defined exactly for char types
if (col->getCharType() != (col->m_cs != NULL)) {
- m_error.code = 703;
+ m_error.code= 703;
DBUG_RETURN(-1);
}
// primary key type check
- if (col->m_pk && ! NdbSqlUtil::usable_in_pk(col->m_type, col->m_cs)) {
- m_error.code = 743;
+ if (col->m_pk &&
+ (err = NdbSqlUtil::check_column_for_pk(col->m_type, col->m_cs)))
+ {
+ m_error.code= err;
+ DBUG_RETURN(-1);
+ }
+ // distribution key not supported for Char attribute
+ if (distKeys && col->m_distributionKey && col->m_cs != NULL) {
+ m_error.code= 745;
DBUG_RETURN(-1);
}
// charset in upper half of precision
@@ -1579,9 +1590,6 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
tmpAttr.AttributeExtPrecision |= (col->m_cs->number << 16);
}
- // DICT will ignore and recompute this
- (void)tmpAttr.translateExtType();
-
tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
BaseString::snprintf(tmpAttr.AttributeDefaultValue,
sizeof(tmpAttr.AttributeDefaultValue),
@@ -1596,7 +1604,7 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
- LinearSectionPtr ptr[3];
+ LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
int ret;
@@ -1629,14 +1637,11 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
DBUG_RETURN(ret);
if (haveAutoIncrement) {
- if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
- autoIncrementValue)) {
- if (ndb.theError.code == 0) {
- m_error.code = 4336;
- ndb.theError = m_error;
- } else
- m_error= ndb.theError;
- ret = -1; // errorcode set in initialize_autoincrement
+ if (ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
+ autoIncrementValue, false) == -1) {
+ DBUG_ASSERT(ndb.theError.code != 0);
+ m_error= ndb.theError;
+ ret = -1;
}
}
}
@@ -1668,11 +1673,12 @@ void
NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
+#if 0
const CreateTableConf* const conf=
CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
Uint32 tableId= conf->tableId;
Uint32 tableVersion= conf->tableVersion;
-
+#endif
m_waiter.signal(NO_WAIT);
}
@@ -1682,7 +1688,7 @@ NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * signal,
{
const CreateTableRef* const ref=
CAST_CONSTPTR(CreateTableRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
@@ -1726,7 +1732,7 @@ NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * signal,
{
const AlterTableRef * const ref =
CAST_CONSTPTR(AlterTableRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
@@ -1741,20 +1747,20 @@ NdbDictionaryImpl::dropTable(const char * name)
DBUG_PRINT("enter",("name: %s", name));
NdbTableImpl * tab = getTable(name);
if(tab == 0){
- return -1;
+ DBUG_RETURN(-1);
}
int ret = dropTable(* tab);
// If table stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
- const char * internalTableName = m_ndb.internalizeTableName(name);
+ const BaseString internalTableName(m_ndb.internalize_table_name(name));
- DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName));
- m_localHash.drop(internalTableName);
+ DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName.c_str()));
+ m_localHash.drop(internalTableName.c_str());
m_globalHash->lock();
tab->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(tab);
- m_globalHash->unlock();
+ m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
@@ -1771,7 +1777,7 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
}
if (impl.m_indexType != NdbDictionary::Index::Undefined) {
- m_receiver.m_error.code = 1228;
+ m_receiver.m_error.code= 1228;
return -1;
}
@@ -1872,32 +1878,37 @@ void
NdbDictInterface::execDROP_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
+ DBUG_ENTER("NdbDictInterface::execDROP_TABLE_CONF");
//DropTableConf* const conf = CAST_CONSTPTR(DropTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
void
NdbDictInterface::execDROP_TABLE_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
+ DBUG_ENTER("NdbDictInterface::execDROP_TABLE_REF");
const DropTableRef* const ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
- m_error.code = ref->errorCode;
+ m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
+ DBUG_VOID_RETURN;
}
int
NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
{
const char * internalTableName = impl.m_internalName.c_str();
-
- m_localHash.drop(internalTableName);
+ DBUG_ENTER("NdbDictionaryImpl::invalidateObject");
+ DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
+ m_localHash.drop(internalTableName);
m_globalHash->lock();
impl.m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(&impl);
m_globalHash->unlock();
- return 0;
+ DBUG_RETURN(0);
}
int
@@ -1916,8 +1927,8 @@ NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
* Get index info
*/
NdbIndexImpl*
-NdbDictionaryImpl::getIndexImpl(const char * externalName,
- const char * internalName)
+NdbDictionaryImpl::getIndexImpl(const char * externalName,
+ const BaseString& internalName)
{
Ndb_local_table_info * info = get_local_table_info(internalName,
false);
@@ -1938,7 +1949,7 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
m_error.code = 4243;
return 0;
}
-
+
/**
* Create index impl
*/
@@ -1957,7 +1968,7 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
int
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
- const NdbTableImpl* tab,
+ NdbTableImpl* tab,
const NdbTableImpl* prim){
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
@@ -1965,22 +1976,49 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
idx->m_indexId = tab->m_tableId;
idx->m_externalName.assign(tab->getName());
idx->m_tableName.assign(prim->m_externalName);
- idx->m_type = tab->m_indexType;
+ NdbDictionary::Index::Type type = idx->m_type = tab->m_indexType;
idx->m_logging = tab->m_logging;
// skip last attribute (NDB$PK or NDB$TNODE)
- for(unsigned i = 0; i+1<tab->m_columns.size(); i++){
+
+ const Uint32 distKeys = prim->m_noOfDistributionKeys;
+ Uint32 keyCount = (distKeys ? distKeys : prim->m_noOfKeys);
+
+ unsigned i;
+ for(i = 0; i+1<tab->m_columns.size(); i++){
+ NdbColumnImpl* org = tab->m_columns[i];
+
NdbColumnImpl* col = new NdbColumnImpl;
// Copy column definition
- *col = *tab->m_columns[i];
+ *col = * org;
idx->m_columns.push_back(col);
+
/**
* reverse map
*/
- int key_id = prim->getColumn(col->getName())->getColumnNo();
+ const NdbColumnImpl* primCol = prim->getColumn(col->getName());
+ int key_id = primCol->getColumnNo();
int fill = -1;
idx->m_key_ids.fill(key_id, fill);
idx->m_key_ids[key_id] = i;
col->m_keyInfoPos = key_id;
+
+ if(type == NdbDictionary::Index::OrderedIndex &&
+ (primCol->m_distributionKey ||
+ (distKeys == 0 && primCol->getPrimaryKey())))
+ {
+ keyCount--;
+ org->m_distributionKey = 1;
+ }
+ }
+
+ if(keyCount == 0)
+ {
+ tab->m_noOfDistributionKeys = (distKeys ? distKeys : prim->m_noOfKeys);
+ }
+ else
+ {
+ for(i = 0; i+1<tab->m_columns.size(); i++)
+ tab->m_columns[i]->m_distributionKey = 0;
}
* dst = idx;
@@ -2009,19 +2047,18 @@ NdbDictInterface::createIndex(Ndb & ndb,
{
//validate();
//aggregate();
- unsigned i;
+ unsigned i, err;
UtilBufferWriter w(m_buffer);
const size_t len = strlen(impl.m_externalName.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
m_error.code = 4241;
return -1;
}
- const char * internalName =
- ndb.internalizeIndexName(&table, impl.getName());
-
+ const BaseString internalName(
+ ndb.internalize_index_name(&table, impl.getName()));
impl.m_internalName.assign(internalName);
- w.add(DictTabInfo::TableName, internalName);
+ w.add(DictTabInfo::TableName, internalName.c_str());
w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
NdbApiSignal tSignal(m_reference);
@@ -2059,41 +2096,19 @@ NdbDictInterface::createIndex(Ndb & ndb,
// Copy column definition
*impl.m_columns[i] = *col;
- if(col->m_pk && col->m_indexOnly){
- m_error.code = 4245;
- return -1;
- }
// index key type check
if (it == DictTabInfo::UniqueHashIndex &&
- ! NdbSqlUtil::usable_in_hash_index(col->m_type, col->m_cs) ||
+ (err = NdbSqlUtil::check_column_for_hash_index(col->m_type, col->m_cs))
+ ||
it == DictTabInfo::OrderedIndex &&
- ! NdbSqlUtil::usable_in_ordered_index(col->m_type, col->m_cs)) {
- m_error.code = 743;
+ (err = NdbSqlUtil::check_column_for_ordered_index(col->m_type, col->m_cs)))
+ {
+ m_error.code = err;
return -1;
}
attributeList.id[i] = col->m_attrId;
}
- if (it == DictTabInfo::UniqueHashIndex) {
- // Sort index attributes according to primary table (using insertion sort)
- 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)) {
- attributeList.id[j] = attributeList.id[j - 1];
- j--;
- }
- attributeList.id[j] = temp;
- }
- // Check for illegal duplicate attributes
- for(i = 0; i<attributeList.sz; i++) {
- if ((i != (attributeList.sz - 1)) &&
- (attributeList.id[i] == attributeList.id[i+1])) {
- m_error.code = 4258;
- return -1;
- }
- }
- }
- LinearSectionPtr ptr[3];
+ LinearSectionPtr ptr[2];
ptr[0].p = (Uint32*)&attributeList;
ptr[0].sz = 1 + attributeList.sz;
ptr[1].p = (Uint32*)m_buffer.get_data();
@@ -2151,20 +2166,20 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
// If index stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
- const char * internalIndexName = (tableName)
+ const BaseString internalIndexName((tableName)
?
- m_ndb.internalizeIndexName(getTable(tableName), indexName)
+ m_ndb.internalize_index_name(getTable(tableName), indexName)
:
- m_ndb.internalizeTableName(indexName); // Index is also a table
-
- m_localHash.drop(internalIndexName);
+ m_ndb.internalize_table_name(indexName)); // Index is also a table
+
+ m_localHash.drop(internalIndexName.c_str());
m_globalHash->lock();
idx->m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(idx->m_table);
- m_globalHash->unlock();
+ m_globalHash->unlock();
return dropIndex(indexName, tableName);
}
-
+
return ret;
}
@@ -2245,614 +2260,6 @@ NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
}
/*****************************************************************
- * Create event
- */
-
-int
-NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
-{
- int i;
- NdbTableImpl* tab = getTable(evnt.getTable());
-
- if(tab == 0){
- // m_error.code = 3249;
- ndbout_c(":createEvent: table %s not found", evnt.getTable());
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s", evnt.getTable());
-#endif
- return -1;
- }
-
- evnt.m_tableId = tab->m_tableId;
- evnt.m_tableImpl = tab;
-#ifdef EVENT_DEBUG
- ndbout_c("Event on tableId=%d", evnt.m_tableId);
-#endif
-
- NdbTableImpl &table = *evnt.m_tableImpl;
-
-
- int attributeList_sz = evnt.m_attrIds.size();
-
- 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));
- } else {
- ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
- evnt.getTable());
- return -1;
- }
- }
-
- evnt.m_attrIds.clear();
-
- attributeList_sz = evnt.m_columns.size();
-#ifdef EVENT_DEBUG
- ndbout_c("creating event %s", evnt.m_externalName.c_str());
- ndbout_c("no of columns %d", evnt.m_columns.size());
-#endif
- int pk_count = 0;
- evnt.m_attrListBitmask.clear();
-
- for(i = 0; i<attributeList_sz; i++){
- const NdbColumnImpl* col =
- table.getColumn(evnt.m_columns[i]->m_name.c_str());
- if(col == 0){
- m_error.code = 4247;
- return -1;
- }
- // Copy column definition
- *evnt.m_columns[i] = *col;
-
- if(col->m_pk){
- pk_count++;
- }
-
- evnt.m_attrListBitmask.set(col->m_attrId);
- }
-
- // Sort index attributes according to primary table (using insertion sort)
- 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)) {
- evnt.m_columns[j] = evnt.m_columns[j - 1];
- j--;
- }
- evnt.m_columns[j] = temp;
- }
- // Check for illegal duplicate attributes
- 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;
- }
- }
-
-#ifdef EVENT_DEBUG
- char buf[128] = {0};
- evnt.m_attrListBitmask.getText(buf);
- ndbout_c("createEvent: mask = %s", buf);
-#endif
-
- // NdbDictInterface m_receiver;
- return m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */);
-}
-
-int
-NdbDictInterface::createEvent(class Ndb & ndb,
- NdbEventImpl & evnt,
- int getFlag)
-{
- NdbApiSignal tSignal(m_reference);
- tSignal.theReceiversBlockNumber = DBDICT;
- tSignal.theVerId_signalNumber = GSN_CREATE_EVNT_REQ;
- if (getFlag)
- tSignal.theLength = CreateEvntReq::SignalLengthGet;
- else
- tSignal.theLength = CreateEvntReq::SignalLengthCreate;
-
- CreateEvntReq * const req = CAST_PTR(CreateEvntReq, tSignal.getDataPtrSend());
-
- req->setUserRef(m_reference);
- req->setUserData(0);
-
- if (getFlag) {
- // getting event from Dictionary
- req->setRequestType(CreateEvntReq::RT_USER_GET);
- } else {
- // creating event in Dictionary
- req->setRequestType(CreateEvntReq::RT_USER_CREATE);
- req->setTableId(evnt.m_tableId);
- req->setAttrListBitmask(evnt.m_attrListBitmask);
- req->setEventType(evnt.mi_type);
- }
-
- UtilBufferWriter w(m_buffer);
-
- const size_t len = strlen(evnt.m_externalName.c_str()) + 1;
- if(len > MAX_TAB_NAME_SIZE) {
- m_error.code = 4241;
- return -1;
- }
-
- w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
-
- if (getFlag == 0)
- w.add(SimpleProperties::StringValue,
- ndb.internalizeTableName(evnt.m_tableName.c_str()));
-
- LinearSectionPtr ptr[3];
- ptr[0].p = (Uint32*)m_buffer.get_data();
- ptr[0].sz = (m_buffer.length()+3) >> 2;
-
- int ret = createEvent(&tSignal, ptr, 1);
-
- if (ret) {
- return ret;
- }
-
- char *dataPtr = (char *)m_buffer.get_data();
- unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
- dataPtr += sizeof(lenCreateEvntConf);
- CreateEvntConf const * evntConf = (CreateEvntConf *)dataPtr;
- dataPtr += lenCreateEvntConf;
-
- // NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData();
-
- if (getFlag) {
- evnt.m_tableId = evntConf->getTableId();
- evnt.m_attrListBitmask = evntConf->getAttrListBitmask();
- evnt.mi_type = evntConf->getEventType();
- evnt.setTable(dataPtr);
- } else {
- if (evnt.m_tableId != evntConf->getTableId() ||
- //evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
- evnt.mi_type != evntConf->getEventType()) {
- ndbout_c("ERROR*************");
- return 1;
- }
- }
-
- evnt.m_eventId = evntConf->getEventId();
- evnt.m_eventKey = evntConf->getEventKey();
-
- return ret;
-}
-
-int
-NdbDictInterface::createEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLSP)
-{
- const int noErrCodes = 1;
- int errCodes[noErrCodes] = {CreateEvntRef::Busy};
- return dictSignal(signal,ptr,noLSP,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- errCodes,noErrCodes, CreateEvntRef::Temporary);
-}
-
-int
-NdbDictionaryImpl::executeSubscribeEvent(NdbEventImpl & ev)
-{
- // NdbDictInterface m_receiver;
- return m_receiver.executeSubscribeEvent(m_ndb, ev);
-}
-
-int
-NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
- NdbEventImpl & evnt)
-{
- NdbApiSignal tSignal(m_reference);
- // tSignal.theReceiversBlockNumber = SUMA;
- tSignal.theReceiversBlockNumber = DBDICT;
- tSignal.theVerId_signalNumber = GSN_SUB_START_REQ;
- tSignal.theLength = SubStartReq::SignalLength2;
-
- SubStartReq * sumaStart = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
-
- sumaStart->subscriptionId = evnt.m_eventId;
- sumaStart->subscriptionKey = evnt.m_eventKey;
- sumaStart->part = SubscriptionData::TableData;
- sumaStart->subscriberData = evnt.m_bufferId & 0xFF;
- sumaStart->subscriberRef = m_reference;
-
- return executeSubscribeEvent(&tSignal, NULL);
-}
-
-int
-NdbDictInterface::executeSubscribeEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3])
-{
- return dictSignal(signal,NULL,0,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- NULL,0);
-}
-
-int
-NdbDictionaryImpl::stopSubscribeEvent(NdbEventImpl & ev)
-{
- // NdbDictInterface m_receiver;
- return m_receiver.stopSubscribeEvent(m_ndb, ev);
-}
-
-int
-NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
- NdbEventImpl & evnt)
-{
-#ifdef EVENT_DEBUG
- ndbout_c("SUB_STOP_REQ");
-#endif
-
- NdbApiSignal tSignal(m_reference);
- // tSignal.theReceiversBlockNumber = SUMA;
- tSignal.theReceiversBlockNumber = DBDICT;
- tSignal.theVerId_signalNumber = GSN_SUB_STOP_REQ;
- tSignal.theLength = SubStopReq::SignalLength;
-
- SubStopReq * sumaStop = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
-
- sumaStop->subscriptionId = evnt.m_eventId;
- sumaStop->subscriptionKey = evnt.m_eventKey;
- sumaStop->subscriberData = evnt.m_bufferId & 0xFF;
- sumaStop->part = (Uint32) SubscriptionData::TableData;
- sumaStop->subscriberRef = m_reference;
-
- return stopSubscribeEvent(&tSignal, NULL);
-}
-
-int
-NdbDictInterface::stopSubscribeEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3])
-{
- return dictSignal(signal,NULL,0,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
- -1,
- NULL,0);
-}
-
-NdbEventImpl *
-NdbDictionaryImpl::getEvent(const char * eventName)
-{
- NdbEventImpl *ev = new NdbEventImpl();
-
- if (ev == NULL) {
- return NULL;
- }
-
- ev->setName(eventName);
-
- int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */);
-
- if (ret) {
- delete ev;
- return NULL;
- }
-
- // We only have the table name with internal name
- ev->setTable(m_ndb.externalizeTableName(ev->getTable()));
- ev->m_tableImpl = getTable(ev->getTable());
-
- // get the columns from the attrListBitmask
-
- NdbTableImpl &table = *ev->m_tableImpl;
- AttributeMask & mask = ev->m_attrListBitmask;
- int attributeList_sz = mask.count();
- int id = -1;
-
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::getEvent attributeList_sz = %d",
- attributeList_sz);
- char buf[128] = {0};
- mask.getText(buf);
- ndbout_c("mask = %s", buf);
-#endif
-
- for(int i = 0; i < attributeList_sz; i++) {
- id++; while (!mask.get(id)) id++;
-
- const NdbColumnImpl* col = table.getColumn(id);
- if(col == 0) {
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::getEvent could not find column id %d", id);
-#endif
- m_error.code = 4247;
- delete ev;
- return NULL;
- }
- NdbColumnImpl* new_col = new NdbColumnImpl;
- // Copy column definition
- *new_col = *col;
-
- ev->m_columns.push_back(new_col);
- }
-
- return ev;
-}
-
-void
-NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_CONF" << endl;
-#endif
- m_buffer.clear();
- unsigned int len = signal->getLength() << 2;
- m_buffer.append((char *)&len, sizeof(len));
- m_buffer.append(signal->getDataPtr(), len);
-
- if (signal->m_noOfSections > 0) {
- m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1);
- }
-
- m_waiter.signal(NO_WAIT);
-}
-
-void
-NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_REF" << endl;
- ndbout << "Exiting" << endl;
- exit(-1);
-#endif
-
- const CreateEvntRef* const ref = CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
- m_error.code = ref->getErrorCode();
-#ifdef EVENT_DEBUG
- ndbout_c("execCREATE_EVNT_REF");
- ndbout_c("ErrorCode %u", ref->getErrorCode());
- ndbout_c("Errorline %u", ref->getErrorLine());
- ndbout_c("ErrorNode %u", ref->getErrorNode());
-#endif
- m_waiter.signal(NO_WAIT);
-}
-
-void
-NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_STOP_CONF" << endl;
-#endif
- // SubRemoveConf * const sumaRemoveConf = CAST_CONSTPTR(SubRemoveConf, signal->getDataPtr());
-
- // Uint32 subscriptionId = sumaRemoveConf->subscriptionId;
- // Uint32 subscriptionKey = sumaRemoveConf->subscriptionKey;
- // Uint32 senderData = sumaRemoveConf->senderData;
-
- m_waiter.signal(NO_WAIT);
-}
-
-void
-NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_STOP_REF" << endl;
-#endif
- // SubRemoveConf * const sumaRemoveRef = CAST_CONSTPTR(SubRemoveRef, signal->getDataPtr());
-
- // Uint32 subscriptionId = sumaRemoveRef->subscriptionId;
- // Uint32 subscriptionKey = sumaRemoveRef->subscriptionKey;
- // Uint32 senderData = sumaRemoveRef->senderData;
-
- m_error.code = 1;
- m_waiter.signal(NO_WAIT);
-}
-
-void
-NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_START_CONF" << endl;
-#endif
- const SubStartConf * const sumaStartConf = CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
-
- // Uint32 subscriptionId = sumaStartConf->subscriptionId;
- // Uint32 subscriptionKey = sumaStartConf->subscriptionKey;
- SubscriptionData::Part part =
- (SubscriptionData::Part)sumaStartConf->part;
- // Uint32 subscriberData = sumaStartConf->subscriberData;
-
- switch(part) {
- case SubscriptionData::MetaData: {
-#ifdef EVENT_DEBUG
- ndbout << "SubscriptionData::MetaData" << endl;
-#endif
- m_error.code = 1;
- break;
- }
- case SubscriptionData::TableData: {
-#ifdef EVENT_DEBUG
- ndbout << "SubscriptionData::TableData" << endl;
-#endif
- break;
- }
- default: {
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictInterface::execSUB_START_CONF wrong data");
-#endif
- m_error.code = 1;
- break;
- }
- }
- m_waiter.signal(NO_WAIT);
-}
-
-void
-NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "Got GSN_SUB_START_REF" << endl;
-#endif
- m_error.code = 1;
- m_waiter.signal(NO_WAIT);
-}
-void
-NdbDictInterface::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
- const SubGcpCompleteRep * const rep = CAST_CONSTPTR(SubGcpCompleteRep, signal->getDataPtr());
-
- const Uint32 gci = rep->gci;
- // const Uint32 senderRef = rep->senderRef;
- const Uint32 subscriberData = rep->subscriberData;
-
- const Uint32 bufferId = subscriberData;
-
- const Uint32 ref = signal->theSendersBlockRef;
-
- NdbApiSignal tSignal(m_reference);
- SubGcpCompleteAcc * acc = CAST_PTR(SubGcpCompleteAcc, tSignal.getDataPtrSend());
-
- acc->rep = *rep;
-
- tSignal.theReceiversBlockNumber = refToBlock(ref);
- tSignal.theVerId_signalNumber = GSN_SUB_GCP_COMPLETE_ACC;
- tSignal.theLength = SubGcpCompleteAcc::SignalLength;
-
- Uint32 aNodeId = refToNode(ref);
-
- // m_transporter->lock_mutex();
- int r;
- r = m_transporter->sendSignal(&tSignal, aNodeId);
- // m_transporter->unlock_mutex();
-
- NdbGlobalEventBufferHandle::latestGCI(bufferId, gci);
-}
-
-void
-NdbDictInterface::execSUB_TABLE_DATA(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- const char * FNAME = "NdbDictInterface::execSUB_TABLE_DATA";
-#endif
- //TODO
- const SubTableData * const sdata = CAST_CONSTPTR(SubTableData, signal->getDataPtr());
-
- // const Uint32 gci = sdata->gci;
- // const Uint32 operation = sdata->operation;
- // const Uint32 tableId = sdata->tableId;
- // const Uint32 noOfAttrs = sdata->noOfAttributes;
- // const Uint32 dataLen = sdata->dataSize;
- const Uint32 subscriberData = sdata->subscriberData;
- // const Uint32 logType = sdata->logType;
-
- for (int i=signal->m_noOfSections;i < 3; i++) {
- ptr[i].p = NULL;
- ptr[i].sz = 0;
- }
-#ifdef EVENT_DEBUG
- ndbout_c("%s: senderData %d, gci %d, operation %d, tableId %d, noOfAttrs %d, dataLen %d",
- FNAME, subscriberData, gci, operation, tableId, noOfAttrs, dataLen);
- ndbout_c("ptr[0] %u %u ptr[1] %u %u ptr[2] %u %u\n",
- ptr[0].p,ptr[0].sz,ptr[1].p,ptr[1].sz,ptr[2].p,ptr[2].sz);
-#endif
- const Uint32 bufferId = subscriberData;
-
- NdbGlobalEventBufferHandle::insertDataL(bufferId,
- sdata, ptr);
-}
-
-/*****************************************************************
- * Drop event
- */
-int
-NdbDictionaryImpl::dropEvent(const char * eventName)
-{
- NdbEventImpl *ev = new NdbEventImpl();
- ev->setName(eventName);
- int ret = m_receiver.dropEvent(*ev);
- delete ev;
-
- // printf("__________________RET %u\n", ret);
- return ret;
-}
-
-int
-NdbDictInterface::dropEvent(const NdbEventImpl &evnt)
-{
- NdbApiSignal tSignal(m_reference);
- tSignal.theReceiversBlockNumber = DBDICT;
- tSignal.theVerId_signalNumber = GSN_DROP_EVNT_REQ;
- tSignal.theLength = DropEvntReq::SignalLength;
-
- DropEvntReq * const req = CAST_PTR(DropEvntReq, tSignal.getDataPtrSend());
-
- req->setUserRef(m_reference);
- req->setUserData(0);
-
- UtilBufferWriter w(m_buffer);
-
- w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
-
- LinearSectionPtr ptr[1];
- ptr[0].p = (Uint32*)m_buffer.get_data();
- ptr[0].sz = (m_buffer.length()+3) >> 2;
-
- return dropEvent(&tSignal, ptr, 1);
-}
-
-int
-NdbDictInterface::dropEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLSP)
-{
- //TODO
- const int noErrCodes = 1;
- int errCodes[noErrCodes] = {DropEvntRef::Busy};
- return dictSignal(signal,ptr,noLSP,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- errCodes,noErrCodes, DropEvntRef::Temporary);
-}
-void
-NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_CONF" << endl;
-#endif
-
- m_waiter.signal(NO_WAIT);
-}
-
-void
-NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_REF" << endl;
-#endif
- const DropEvntRef* const ref = CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
- m_error.code = ref->getErrorCode();
-
-#if 0
- ndbout_c("execDROP_EVNT_REF");
- ndbout_c("ErrorCode %u", ref->getErrorCode());
- ndbout_c("Errorline %u", ref->getErrorLine());
- ndbout_c("ErrorNode %u", ref->getErrorNode());
-#endif
-
- m_waiter.signal(NO_WAIT);
-}
-
-/*****************************************************************
* List objects or indexes
*/
int
@@ -2914,7 +2321,7 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
}
if (! ok) {
// bad signal data
- m_error.code = 4213;
+ m_error.code= 4213;
return -1;
}
list.count = count;
@@ -2936,8 +2343,6 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
BaseString schemaName;
BaseString objectName;
if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
- (element.type == NdbDictionary::Object::HashIndex) ||
- (element.type == NdbDictionary::Object::UniqueOrderedIndex) ||
(element.type == NdbDictionary::Object::OrderedIndex)) {
char * indexName = new char[n << 2];
memcpy(indexName, &data[pos], n << 2);
@@ -2982,7 +2387,7 @@ NdbDictInterface::listObjects(NdbApiSignal* signal)
m_transporter->lock_mutex();
Uint16 aNodeId = m_transporter->get_an_alive_node();
if (aNodeId == 0) {
- m_error.code = 4009;
+ m_error.code= 4009;
m_transporter->unlock_mutex();
return -1;
}
@@ -2990,7 +2395,7 @@ NdbDictInterface::listObjects(NdbApiSignal* signal)
m_transporter->unlock_mutex();
continue;
}
- m_error.code = 0;
+ m_error.code= 0;
m_waiter.m_node = aNodeId;
m_waiter.m_state = WAIT_LIST_TABLES_CONF;
m_waiter.wait(WAITFOR_RESPONSE_TIMEOUT);
@@ -3019,6 +2424,7 @@ NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal,
}
template class Vector<int>;
+template class Vector<Uint16>;
template class Vector<Uint32>;
template class Vector<Vector<Uint32> >;
template class Vector<NdbTableImpl*>;
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index ad587a10e1d..6a86ee44bfb 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -19,7 +19,6 @@
#include <ndb_types.h>
#include <kernel_types.h>
-#include <ndb_limits.h>
#include <NdbError.hpp>
#include <BaseString.hpp>
#include <Vector.hpp>
@@ -63,12 +62,8 @@ public:
CHARSET_INFO * m_cs; // not const in MySQL
bool m_pk;
- bool m_tupleKey;
bool m_distributionKey;
- bool m_distributionGroup;
- int m_distributionGroupBits;
bool m_nullable;
- bool m_indexOnly;
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
BaseString m_defaultValue;
@@ -77,13 +72,13 @@ public:
/**
* Internal types and sizes, and aggregates
*/
- Uint32 m_attrType; // type outsize API and DICT
Uint32 m_attrSize; // element size (size when arraySize==1)
Uint32 m_arraySize; // length or length+2 for Var* types
Uint32 m_keyInfoPos;
- Uint32 m_extType; // used by restore (kernel type in versin v2x)
+ // TODO: use bits in attr desc 2
bool getInterpretableType() const ;
bool getCharType() const;
+ bool getStringType() const;
bool getBlobType() const;
/**
@@ -96,6 +91,10 @@ public:
NdbDictionary::Column * m_facade;
static NdbDictionary::Column * create_psuedo(const char *);
+
+ // Get total length in bytes, used by NdbOperation
+ // backported from 5.1
+ bool get_var_length(const void* value, Uint32& len) const;
};
class NdbTableImpl : public NdbDictionary::Table, public NdbDictObjectImpl {
@@ -123,13 +122,23 @@ public:
Vector<Uint32> m_columnHash;
Vector<NdbColumnImpl *> m_columns;
void buildColumnHash();
-
+
+ /**
+ * Fragment info
+ */
+ Uint32 m_hashValueMask;
+ Uint32 m_hashpointerValue;
+ Vector<Uint16> m_fragments;
+
+ Uint64 m_max_rows;
+ Uint64 m_min_rows;
+
bool m_logging;
int m_kvalue;
int m_minLoadFactor;
int m_maxLoadFactor;
- int m_keyLenInWords;
- int m_fragmentCount;
+ Uint16 m_keyLenInWords;
+ Uint16 m_fragmentCount;
NdbDictionaryImpl * m_dictionary;
NdbIndexImpl * m_index;
@@ -147,21 +156,26 @@ public:
/**
* Aggregates
*/
- Uint32 m_noOfKeys;
- unsigned short m_sizeOfKeysInWords;
- unsigned short m_noOfBlobs;
+ Uint8 m_noOfKeys;
+ Uint8 m_noOfDistributionKeys;
+ Uint8 m_noOfBlobs;
+
+ Uint8 m_replicaCount;
/**
* Equality/assign
*/
bool equal(const NdbTableImpl&) const;
void assign(const NdbTableImpl&);
- void clearNewProperties();
- void copyNewProperties();
static NdbTableImpl & getImpl(NdbDictionary::Table & t);
static NdbTableImpl & getImpl(const NdbDictionary::Table & t);
NdbDictionary::Table * m_facade;
+
+ /**
+ * Return count
+ */
+ Uint32 get_nodes(Uint32 hashValue, const Uint16** nodes) const ;
};
class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
@@ -170,6 +184,7 @@ public:
NdbIndexImpl(NdbDictionary::Index &);
~NdbIndexImpl();
+ void init();
void setName(const char * name);
const char * getName() const;
void setTable(const char * table);
@@ -193,51 +208,6 @@ public:
NdbDictionary::Index * m_facade;
};
-class NdbEventImpl : public NdbDictionary::Event, public NdbDictObjectImpl {
-public:
- NdbEventImpl();
- NdbEventImpl(NdbDictionary::Event &);
- ~NdbEventImpl();
-
- void setName(const char * name);
- const char * getName() const;
- void setTable(const char * table);
- const char * getTable() const;
- void addTableEvent(const NdbDictionary::Event::TableEvent t);
- void setDurability(const NdbDictionary::Event::EventDurability d);
- void addEventColumn(const NdbColumnImpl &c);
-
- void print() {
- ndbout_c("NdbEventImpl: id=%d, key=%d",
- m_eventId,
- m_eventKey);
- };
-
- Uint32 m_eventId;
- Uint32 m_eventKey;
- Uint32 m_tableId;
- AttributeMask m_attrListBitmask;
- //BaseString m_internalName;
- BaseString m_externalName;
- Uint32 mi_type;
- NdbDictionary::Event::EventDurability m_dur;
-
-
- NdbTableImpl *m_tableImpl;
- BaseString m_tableName;
- Vector<NdbColumnImpl *> m_columns;
- Vector<unsigned> m_attrIds;
-
- int m_bufferId;
-
- NdbEventOperation *eventOp;
-
- static NdbEventImpl & getImpl(NdbDictionary::Event & t);
- static NdbEventImpl & getImpl(const NdbDictionary::Event & t);
- NdbDictionary::Event * m_facade;
-};
-
-
class NdbDictInterface {
public:
NdbDictInterface(NdbError& err) : m_error(err) {
@@ -275,29 +245,17 @@ public:
const NdbTableImpl &);
int createIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
- int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag);
- int createEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
-
int dropTable(const NdbTableImpl &);
int dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
int dropIndex(const NdbIndexImpl &, const NdbTableImpl &);
int dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
- int dropEvent(const NdbEventImpl &);
- int dropEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP);
-
- int executeSubscribeEvent(class Ndb & ndb, NdbEventImpl &);
- int executeSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
- int stopSubscribeEvent(class Ndb & ndb, NdbEventImpl &);
- int stopSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]);
-
int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData, bool fullyQualifiedNames);
int listObjects(NdbApiSignal* signal);
- NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames);
- NdbTableImpl * getTable(const char * name, bool fullyQualifiedNames);
+/* NdbTableImpl * getTable(int tableId, bool fullyQualifiedNames); */
+ NdbTableImpl * getTable(const BaseString& name, bool fullyQualifiedNames);
NdbTableImpl * getTable(class NdbApiSignal * signal,
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames);
@@ -307,8 +265,8 @@ public:
bool fullyQualifiedNames);
static int create_index_obj_from_table(NdbIndexImpl ** dst,
- const NdbTableImpl*,
- const NdbTableImpl*);
+ NdbTableImpl* index_table,
+ const NdbTableImpl* primary_table);
NdbError & m_error;
private:
@@ -338,17 +296,6 @@ private:
void execDROP_INDX_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execDROP_INDX_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execCREATE_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execCREATE_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_START_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_START_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_TABLE_DATA(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_GCP_COMPLETE_REP(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_STOP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execSUB_STOP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execDROP_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
- void execDROP_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
-
void execDROP_TABLE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execDROP_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
void execLIST_TABLES_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]);
@@ -365,7 +312,7 @@ public:
bool setTransporter(class Ndb * ndb, class TransporterFacade * tf);
bool setTransporter(class TransporterFacade * tf);
-
+
int createTable(NdbTableImpl &t);
int createBlobTables(NdbTableImpl &);
int addBlobTables(NdbTableImpl &);
@@ -383,25 +330,16 @@ public:
NdbTableImpl * getIndexTable(NdbIndexImpl * index,
NdbTableImpl * table);
- int createEvent(NdbEventImpl &);
- int dropEvent(const char * eventName);
-
- int executeSubscribeEvent(NdbEventImpl &);
- int stopSubscribeEvent(NdbEventImpl &);
-
int listObjects(List& list, NdbDictionary::Object::Type type);
int listIndexes(List& list, Uint32 indexId);
-
+
NdbTableImpl * getTable(const char * tableName, void **data= 0);
- Ndb_local_table_info * get_local_table_info(const char * internalName,
- bool do_add_blob_tables);
+ Ndb_local_table_info* get_local_table_info(
+ const BaseString& internalTableName, bool do_add_blob_tables);
NdbIndexImpl * getIndex(const char * indexName,
const char * tableName);
NdbIndexImpl * getIndex(const char * indexName,
NdbTableImpl * table);
- NdbIndexImpl * getIndexImpl(const char * name, const char * internalName);
- NdbEventImpl * getEvent(const char * eventName);
- NdbEventImpl * getEventImpl(const char * internalName);
const NdbError & getNdbError() const;
NdbError m_error;
@@ -417,22 +355,12 @@ public:
NdbDictInterface m_receiver;
Ndb & m_ndb;
private:
- Ndb_local_table_info * fetchGlobalTableImpl(const char * internalName);
+ NdbIndexImpl * getIndexImpl(const char * name,
+ const BaseString& internalName);
+ Ndb_local_table_info * fetchGlobalTableImpl(const BaseString& internalName);
};
inline
-NdbEventImpl &
-NdbEventImpl::getImpl(const NdbDictionary::Event & t){
- return t.m_impl;
-}
-
-inline
-NdbEventImpl &
-NdbEventImpl::getImpl(NdbDictionary::Event & t){
- return t.m_impl;
-}
-
-inline
NdbColumnImpl &
NdbColumnImpl::getImpl(NdbDictionary::Column & t){
return t.m_impl;
@@ -456,7 +384,19 @@ bool
NdbColumnImpl::getCharType() const {
return (m_type == NdbDictionary::Column::Char ||
m_type == NdbDictionary::Column::Varchar ||
- m_type == NdbDictionary::Column::Text);
+ m_type == NdbDictionary::Column::Text ||
+ m_type == NdbDictionary::Column::Longvarchar);
+}
+
+inline
+bool
+NdbColumnImpl::getStringType() const {
+ return (m_type == NdbDictionary::Column::Char ||
+ m_type == NdbDictionary::Column::Varchar ||
+ m_type == NdbDictionary::Column::Longvarchar ||
+ m_type == NdbDictionary::Column::Binary ||
+ m_type == NdbDictionary::Column::Varbinary ||
+ m_type == NdbDictionary::Column::Longvarbinary);
}
inline
@@ -467,6 +407,27 @@ NdbColumnImpl::getBlobType() const {
}
inline
+bool
+NdbColumnImpl::get_var_length(const void* value, Uint32& len) const
+{
+ Uint32 max_len = m_attrSize * m_arraySize;
+ switch (m_type) {
+ case NdbDictionary::Column::Varchar:
+ case NdbDictionary::Column::Varbinary:
+ len = 1 + *((Uint8*)value);
+ break;
+ case NdbDictionary::Column::Longvarchar:
+ case NdbDictionary::Column::Longvarbinary:
+ len = 2 + uint2korr((char*)value);
+ break;
+ default:
+ len = max_len;
+ return true;
+ }
+ return (len <= max_len);
+}
+
+inline
NdbTableImpl &
NdbTableImpl::getImpl(NdbDictionary::Table & t){
return t.m_impl;
@@ -537,7 +498,7 @@ NdbTableImpl::getColumn(const char * name){
do {
if(hashValue == (tmp & 0xFFFE)){
NdbColumnImpl* col = cols[tmp >> 16];
- if(strcmp(name, col->m_name.c_str()) == 0){
+ if(strncmp(name, col->m_name.c_str(), col->m_name.length()) == 0){
return col;
}
}
@@ -613,26 +574,27 @@ NdbDictionaryImpl::getImpl(const NdbDictionary::Dictionary & t){
*/
inline
-NdbTableImpl *
-NdbDictionaryImpl::getTable(const char * tableName, void **data)
+NdbTableImpl *
+NdbDictionaryImpl::getTable(const char * table_name, void **data)
{
+ const BaseString internal_tabname(m_ndb.internalize_table_name(table_name));
Ndb_local_table_info *info=
- get_local_table_info(m_ndb.internalizeTableName(tableName), true);
- if (info == 0) {
+ get_local_table_info(internal_tabname, true);
+ if (info == 0)
return 0;
- }
- if (data) {
+
+ if (data)
*data= info->m_local_data;
- }
+
return info->m_table_impl;
}
inline
Ndb_local_table_info *
-NdbDictionaryImpl::get_local_table_info(const char * internalTableName,
+NdbDictionaryImpl::get_local_table_info(const BaseString& internalTableName,
bool do_add_blob_tables)
{
- Ndb_local_table_info *info= m_localHash.get(internalTableName);
+ Ndb_local_table_info *info= m_localHash.get(internalTableName.c_str());
if (info == 0) {
info= fetchGlobalTableImpl(internalTableName);
if (info == 0) {
@@ -648,40 +610,43 @@ NdbDictionaryImpl::get_local_table_info(const char * internalTableName,
inline
NdbIndexImpl *
-NdbDictionaryImpl::getIndex(const char * indexName,
- const char * tableName)
+NdbDictionaryImpl::getIndex(const char * index_name,
+ const char * table_name)
{
- return getIndex(indexName, (tableName) ? getTable(tableName) : NULL);
+ return getIndex(index_name, (table_name) ? getTable(table_name) : NULL);
}
inline
NdbIndexImpl *
-NdbDictionaryImpl::getIndex(const char * indexName,
+NdbDictionaryImpl::getIndex(const char * index_name,
NdbTableImpl * table)
{
- if (table || m_ndb.usingFullyQualifiedNames()) {
- const char * internalIndexName = 0;
- if (table) {
- internalIndexName = m_ndb.internalizeIndexName(table, indexName);
- } else {
- internalIndexName =
- m_ndb.internalizeTableName(indexName); // Index is also a table
- }
- if (internalIndexName) {
- Ndb_local_table_info * info = get_local_table_info(internalIndexName,
- false);
- if (info) {
- NdbTableImpl * tab = info->m_table_impl;
+ if (table || m_ndb.usingFullyQualifiedNames())
+ {
+ const BaseString internal_indexname(
+ (table)
+ ?
+ m_ndb.internalize_index_name(table, index_name)
+ :
+ m_ndb.internalize_table_name(index_name)); // Index is also a table
+
+ if (internal_indexname.length())
+ {
+ Ndb_local_table_info * info=
+ get_local_table_info(internal_indexname, false);
+ if (info)
+ {
+ NdbTableImpl * tab= info->m_table_impl;
if (tab->m_index == 0)
- tab->m_index = getIndexImpl(indexName, internalIndexName);
+ tab->m_index= getIndexImpl(index_name, internal_indexname);
if (tab->m_index != 0)
- tab->m_index->m_table = tab;
+ tab->m_index->m_table= tab;
return tab->m_index;
}
}
}
- m_error.code = 4243;
+ m_error.code= 4243;
return 0;
}
diff --git a/ndb/src/ndbapi/NdbEventOperation.cpp b/ndb/src/ndbapi/NdbEventOperation.cpp
index d209293f8b0..e99cad918c5 100644
--- a/ndb/src/ndbapi/NdbEventOperation.cpp
+++ b/ndb/src/ndbapi/NdbEventOperation.cpp
@@ -15,23 +15,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbEventOperation.cpp
- * Include:
- * Link:
- * Author: Tomas Ulin MySQL AB
- * Date: 2003-11-21
- * Version: 0.1
- * Description: Event support
- * Documentation:
- * Adjust: 2003-11-21 Tomas Ulin First version.
- ****************************************************************************/
-
#include <Ndb.hpp>
-#include <signaldata/SumaImpl.hpp>
+#include <NdbError.hpp>
#include <portlib/NdbMem.h>
-#include <transporter/TransporterDefinitions.hpp>
-#include <NdbEventOperation.hpp>
#include "NdbEventOperationImpl.hpp"
#include "NdbDictionaryImpl.hpp"
@@ -123,3 +109,7 @@ NdbEventOperation::wait(void *p, int aMillisecondNumber)
NdbEventOperation::NdbEventOperation(NdbEventOperationImpl& impl)
: m_impl(impl) {}
+const struct NdbError &
+NdbEventOperation::getNdbError() const {
+ return m_impl.getNdbError();
+}
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.cpp b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
index 87bbca5fc71..9c147be9f16 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.cpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.cpp
@@ -55,14 +55,17 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
const char* eventName,
const int bufferLength)
: NdbEventOperation(*this), m_ndb(theNdb),
- m_state(ERROR), m_bufferL(bufferLength)
+ m_state(EO_ERROR), m_bufferL(bufferLength)
{
-
m_eventId = 0;
- theFirstRecAttrs[0] = NULL;
- theCurrentRecAttrs[0] = NULL;
- theFirstRecAttrs[1] = NULL;
- theCurrentRecAttrs[1] = NULL;
+ theFirstPkAttrs[0] = NULL;
+ theCurrentPkAttrs[0] = NULL;
+ theFirstPkAttrs[1] = NULL;
+ theCurrentPkAttrs[1] = NULL;
+ theFirstDataAttrs[0] = NULL;
+ theCurrentDataAttrs[0] = NULL;
+ theFirstDataAttrs[1] = NULL;
+ theCurrentDataAttrs[1] = NULL;
sdata = NULL;
ptr[0].p = NULL;
ptr[1].p = NULL;
@@ -71,16 +74,17 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
// we should lookup id in Dictionary, TODO
// also make sure we only have one listener on each event
- if (!m_ndb) { ndbout_c("m_ndb=NULL"); return; }
+ if (!m_ndb) abort();
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
- if (!myDict) { ndbout_c("getDictionary=NULL"); return; }
+ if (!myDict) { m_error.code= m_ndb->getNdbError().code; return; }
const NdbDictionary::Event *myEvnt = myDict->getEvent(eventName);
- if (!myEvnt) { ndbout_c("getEvent()=NULL"); return; }
+ if (!myEvnt) { m_error.code= myDict->getNdbError().code; return; }
m_eventImpl = &myEvnt->m_impl;
- if (!m_eventImpl) { ndbout_c("m_impl=NULL"); return; }
+
+ m_eventId = m_eventImpl->m_eventId;
m_bufferHandle = m_ndb->getGlobalEventBufferHandle();
if (m_bufferHandle->m_bufferL > 0)
@@ -88,25 +92,30 @@ NdbEventOperationImpl::NdbEventOperationImpl(NdbEventOperation &N,
else
m_bufferHandle->m_bufferL = m_bufferL;
- m_state = CREATED;
+ m_state = EO_CREATED;
}
NdbEventOperationImpl::~NdbEventOperationImpl()
{
int i;
- if (sdata) NdbMem_Free(sdata);
- for (i=0 ; i<3; i++) {
- if (ptr[i].p) NdbMem_Free(ptr[i].p);
+ if (sdata) NdbMem_Free((char*)sdata);
+ for (i=0 ; i<2; i++) {
+ NdbRecAttr *p = theFirstPkAttrs[i];
+ while (p) {
+ NdbRecAttr *p_next = p->next();
+ m_ndb->releaseRecAttr(p);
+ p = p_next;
+ }
}
for (i=0 ; i<2; i++) {
- NdbRecAttr *p = theFirstRecAttrs[i];
+ NdbRecAttr *p = theFirstDataAttrs[i];
while (p) {
NdbRecAttr *p_next = p->next();
m_ndb->releaseRecAttr(p);
p = p_next;
}
}
- if (m_state == NdbEventOperation::EXECUTING) {
+ if (m_state == EO_EXECUTING) {
stop();
// m_bufferHandle->dropSubscribeEvent(m_bufferId);
; // We should send stop signal here
@@ -122,36 +131,50 @@ NdbEventOperationImpl::getState()
NdbRecAttr*
NdbEventOperationImpl::getValue(const char *colName, char *aValue, int n)
{
- if (m_state != NdbEventOperation::CREATED) {
+ DBUG_ENTER("NdbEventOperationImpl::getValue");
+ if (m_state != EO_CREATED) {
ndbout_c("NdbEventOperationImpl::getValue may only be called between instantiation and execute()");
- return NULL;
+ DBUG_RETURN(NULL);
}
NdbColumnImpl *tAttrInfo = m_eventImpl->m_tableImpl->getColumn(colName);
if (tAttrInfo == NULL) {
ndbout_c("NdbEventOperationImpl::getValue attribute %s not found",colName);
- return NULL;
+ DBUG_RETURN(NULL);
}
- return NdbEventOperationImpl::getValue(tAttrInfo, aValue, n);
+ DBUG_RETURN(NdbEventOperationImpl::getValue(tAttrInfo, aValue, n));
}
NdbRecAttr*
NdbEventOperationImpl::getValue(const NdbColumnImpl *tAttrInfo, char *aValue, int n)
{
+ DBUG_ENTER("NdbEventOperationImpl::getValue");
// Insert Attribute Id into ATTRINFO part.
- NdbRecAttr *&theFirstRecAttr = theFirstRecAttrs[n];
- NdbRecAttr *&theCurrentRecAttr = theCurrentRecAttrs[n];
-
+
+ NdbRecAttr **theFirstAttr;
+ NdbRecAttr **theCurrentAttr;
+
+ if (tAttrInfo->getPrimaryKey())
+ {
+ theFirstAttr = &theFirstPkAttrs[n];
+ theCurrentAttr = &theCurrentPkAttrs[n];
+ }
+ else
+ {
+ theFirstAttr = &theFirstDataAttrs[n];
+ theCurrentAttr = &theCurrentDataAttrs[n];
+ }
+
/************************************************************************
* Get a Receive Attribute object and link it into the operation object.
************************************************************************/
- NdbRecAttr *tRecAttr = m_ndb->getRecAttr();
- if (tRecAttr == NULL) {
+ NdbRecAttr *tAttr = m_ndb->getRecAttr();
+ if (tAttr == NULL) {
exit(-1);
//setErrorCodeAbort(4000);
- return NULL;
+ DBUG_RETURN(NULL);
}
/**********************************************************************
@@ -159,63 +182,65 @@ NdbEventOperationImpl::getValue(const NdbColumnImpl *tAttrInfo, char *aValue, in
* the RecAttr object
* Also set attribute size, array size and attribute type
********************************************************************/
- if (tRecAttr->setup(tAttrInfo, aValue)) {
+ if (tAttr->setup(tAttrInfo, aValue)) {
//setErrorCodeAbort(4000);
- m_ndb->releaseRecAttr(tRecAttr);
+ m_ndb->releaseRecAttr(tAttr);
exit(-1);
- return NULL;
+ DBUG_RETURN(NULL);
}
//theErrorLine++;
- tRecAttr->setNULL();
+ tAttr->setUNDEFINED();
// We want to keep the list sorted to make data insertion easier later
- if (theFirstRecAttr == NULL) {
- theFirstRecAttr = tRecAttr;
- theCurrentRecAttr = tRecAttr;
- tRecAttr->next(NULL);
+
+ if (*theFirstAttr == NULL) {
+ *theFirstAttr = tAttr;
+ *theCurrentAttr = tAttr;
+ tAttr->next(NULL);
} else {
Uint32 tAttrId = tAttrInfo->m_attrId;
- if (tAttrId > theCurrentRecAttr->attrId()) { // right order
- theCurrentRecAttr->next(tRecAttr);
- tRecAttr->next(NULL);
- theCurrentRecAttr = tRecAttr;
- } else if (theFirstRecAttr->next() == NULL || // only one in list
- theFirstRecAttr->attrId() > tAttrId) {// or first
- tRecAttr->next(theFirstRecAttr);
- theFirstRecAttr = tRecAttr;
+ if (tAttrId > (*theCurrentAttr)->attrId()) { // right order
+ (*theCurrentAttr)->next(tAttr);
+ tAttr->next(NULL);
+ *theCurrentAttr = tAttr;
+ } else if ((*theFirstAttr)->next() == NULL || // only one in list
+ (*theFirstAttr)->attrId() > tAttrId) {// or first
+ tAttr->next(*theFirstAttr);
+ *theFirstAttr = tAttr;
} else { // at least 2 in list and not first and not last
- NdbRecAttr *p = theFirstRecAttr;
+ NdbRecAttr *p = *theFirstAttr;
NdbRecAttr *p_next = p->next();
while (tAttrId > p_next->attrId()) {
p = p_next;
p_next = p->next();
}
if (tAttrId == p_next->attrId()) { // Using same attribute twice
- tRecAttr->release(); // do I need to do this?
- m_ndb->releaseRecAttr(tRecAttr);
+ tAttr->release(); // do I need to do this?
+ m_ndb->releaseRecAttr(tAttr);
exit(-1);
- return NULL;
+ DBUG_RETURN(NULL);
}
// this is it, between p and p_next
- p->next(tRecAttr);
- tRecAttr->next(p_next);
+ p->next(tAttr);
+ tAttr->next(p_next);
}
}
-
- return tRecAttr;
+ DBUG_RETURN(tAttr);
}
int
NdbEventOperationImpl::execute()
{
+ DBUG_ENTER("NdbEventOperationImpl::execute");
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) {
- ndbout_c("NdbEventOperation::execute(): getDictionary=NULL");
- return 0;
+ m_error.code= m_ndb->getNdbError().code;
+ DBUG_RETURN(-1);
}
- if (theFirstRecAttrs[0] == NULL) { // defaults to get all
+ if (theFirstPkAttrs[0] == NULL &&
+ theFirstDataAttrs[0] == NULL) { // defaults to get all
}
@@ -223,13 +248,18 @@ NdbEventOperationImpl::execute()
int hasSubscriber;
- m_bufferId =
- m_bufferHandle->prepareAddSubscribeEvent(m_eventImpl->m_eventId,
- hasSubscriber /* return value */);
+ int r= m_bufferHandle->prepareAddSubscribeEvent(this,
+ hasSubscriber /*return value*/);
+
+ if (r < 0)
+ {
+ m_error.code= 4709;
+ DBUG_RETURN(-1);
+ }
- m_eventImpl->m_bufferId = m_bufferId;
+ m_eventImpl->m_bufferId = m_bufferId = (Uint32)r;
- int r = -1;
+ r = -1;
if (m_bufferId >= 0) {
// now we check if there's already a subscriber
@@ -241,30 +271,33 @@ NdbEventOperationImpl::execute()
if (r) {
//Error
m_bufferHandle->unprepareAddSubscribeEvent(m_bufferId);
- m_state = NdbEventOperation::ERROR;
+ m_state = EO_ERROR;
} else {
m_bufferHandle->addSubscribeEvent(m_bufferId, this);
- m_state = NdbEventOperation::EXECUTING;
+ m_state = EO_EXECUTING;
}
} else {
//Error
- m_state = NdbEventOperation::ERROR;
+ m_state = EO_ERROR;
}
- return r;
+ DBUG_RETURN(r);
}
int
NdbEventOperationImpl::stop()
{
- if (m_state != NdbEventOperation::EXECUTING)
- return -1;
+ DBUG_ENTER("NdbEventOperationImpl::stop");
+ if (m_state != EO_EXECUTING)
+ {
+ DBUG_RETURN(-1);
+ }
// ndbout_c("NdbEventOperation::stopping()");
NdbDictionary::Dictionary *myDict = m_ndb->getDictionary();
if (!myDict) {
- ndbout_c("NdbEventOperation::stop(): getDictionary=NULL");
- return 0;
+ m_error.code= m_ndb->getNdbError().code;
+ DBUG_RETURN(-1);
}
NdbDictionaryImpl & myDictImpl = NdbDictionaryImpl::getImpl(*myDict);
@@ -275,8 +308,8 @@ NdbEventOperationImpl::stop()
hasSubscriber /* return value */);
if (ret < 0) {
- ndbout_c("prepareDropSubscribeEvent failed");
- return -1;
+ m_error.code= 4712;
+ DBUG_RETURN(-1);
}
// m_eventImpl->m_bufferId = m_bufferId;
@@ -293,17 +326,17 @@ NdbEventOperationImpl::stop()
if (r) {
//Error
m_bufferHandle->unprepareDropSubscribeEvent(m_bufferId);
- m_state = NdbEventOperation::ERROR;
+ m_error.code= myDictImpl.m_error.code;
+ m_state = EO_ERROR;
} else {
#ifdef EVENT_DEBUG
ndbout_c("NdbEventOperation::dropping()");
#endif
m_bufferHandle->dropSubscribeEvent(m_bufferId);
- m_state = NdbEventOperation::CREATED;
+ m_state = EO_CREATED;
}
-
- return r;
+ DBUG_RETURN(r);
}
bool
@@ -327,6 +360,7 @@ NdbEventOperationImpl::getLatestGCI()
int
NdbEventOperationImpl::next(int *pOverrun)
{
+ DBUG_ENTER("NdbEventOperationImpl::next");
int nr = 10000; // a high value
int tmpOverrun = 0;
int *ptmpOverrun;
@@ -343,7 +377,10 @@ NdbEventOperationImpl::next(int *pOverrun)
*pOverrun = tmpOverrun;
}
- if (r <= 0) return r; // no data
+ if (r <= 0)
+ {
+ DBUG_RETURN(r); // no data
+ }
if (r < nr) r = nr; else nr--; // we don't want to be stuck here forever
@@ -352,8 +389,13 @@ NdbEventOperationImpl::next(int *pOverrun)
#endif
// now move the data into the RecAttrs
- if ((theFirstRecAttrs[0] == NULL) &&
- (theFirstRecAttrs[1] == NULL)) return r;
+ if ((theFirstPkAttrs[0] == NULL) &&
+ (theFirstPkAttrs[1] == NULL) &&
+ (theFirstDataAttrs[0] == NULL) &&
+ (theFirstDataAttrs[1] == NULL))
+ {
+ DBUG_RETURN(r);
+ }
// no copying since no RecAttr's
@@ -364,20 +406,37 @@ NdbEventOperationImpl::next(int *pOverrun)
#ifdef EVENT_DEBUG
int i;
printf("after values sz=%u\n", ptr[1].sz);
- for (i=0; i < ptr[1].sz; i++)
+ for(i=0; i < (int)ptr[1].sz; i++)
printf ("H'%.8X ",ptr[1].p[i]);
printf("\n");
printf("before values sz=%u\n", ptr[2].sz);
- for (i=0; i < ptr[2].sz; i++)
+ for(i=0; i < (int)ptr[2].sz; i++)
printf ("H'%.8X ",ptr[2].p[i]);
printf("\n");
#endif
- NdbRecAttr *tWorkingRecAttr = theFirstRecAttrs[0];
-
// copy data into the RecAttr's
// we assume that the respective attribute lists are sorted
+ // first the pk's
+ {
+ NdbRecAttr *tAttr= theFirstPkAttrs[0];
+ while(tAttr)
+ {
+ assert(aAttrPtr < aAttrEndPtr);
+ unsigned tDataSz= AttributeHeader(*aAttrPtr).getDataSize();
+ assert(tAttr->attrId() ==
+ AttributeHeader(*aAttrPtr).getAttributeId());
+ assert(tAttr->receive_data(aDataPtr, tDataSz));
+ // next
+ aAttrPtr++;
+ aDataPtr+= tDataSz;
+ tAttr= tAttr->next();
+ }
+ }
+
+ NdbRecAttr *tWorkingRecAttr = theFirstDataAttrs[0];
+
Uint32 tRecAttrId;
Uint32 tAttrId;
Uint32 tDataSz;
@@ -389,7 +448,7 @@ NdbEventOperationImpl::next(int *pOverrun)
while (tAttrId > tRecAttrId) {
//printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
if (tWorkingRecAttr == NULL)
break;
@@ -401,32 +460,25 @@ NdbEventOperationImpl::next(int *pOverrun)
//printf("[%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
if (tAttrId == tRecAttrId) {
- if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey())
- hasSomeData++;
+ hasSomeData++;
//printf("set!\n");
- tWorkingRecAttr->receive_data(aDataPtr, tDataSz);
-
- // move forward, data has already moved forward
- aAttrPtr++;
- aDataPtr += tDataSz;
+ assert(tWorkingRecAttr->receive_data(aDataPtr, tDataSz));
tWorkingRecAttr = tWorkingRecAttr->next();
- } else {
- // move only attr forward
- aAttrPtr++;
- aDataPtr += tDataSz;
}
+ aAttrPtr++;
+ aDataPtr += tDataSz;
}
while (tWorkingRecAttr != NULL) {
tRecAttrId = tWorkingRecAttr->attrId();
//printf("set undefined [%u] %u %u [%u]\n", tAttrId, tDataSz, *aDataPtr, tRecAttrId);
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
}
- tWorkingRecAttr = theFirstRecAttrs[1];
+ tWorkingRecAttr = theFirstDataAttrs[1];
aDataPtr = ptr[2].p;
Uint32 *aDataEndPtr = aDataPtr + ptr[2].sz;
while ((aDataPtr < aDataEndPtr) && (tWorkingRecAttr != NULL)) {
@@ -435,7 +487,7 @@ NdbEventOperationImpl::next(int *pOverrun)
tDataSz = AttributeHeader(*aDataPtr).getDataSize();
aDataPtr++;
while (tAttrId > tRecAttrId) {
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
if (tWorkingRecAttr == NULL)
break;
@@ -444,27 +496,25 @@ NdbEventOperationImpl::next(int *pOverrun)
if (tWorkingRecAttr == NULL)
break;
if (tAttrId == tRecAttrId) {
- if (!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey())
- hasSomeData++;
+ assert(!m_eventImpl->m_tableImpl->getColumn(tRecAttrId)->getPrimaryKey());
+ hasSomeData++;
- tWorkingRecAttr->receive_data(aDataPtr, tDataSz);
- aDataPtr += tDataSz;
- // move forward, data+attr has already moved forward
+ assert(tWorkingRecAttr->receive_data(aDataPtr, tDataSz));
tWorkingRecAttr = tWorkingRecAttr->next();
- } else {
- // move only data+attr forward
- aDataPtr += tDataSz;
}
+ aDataPtr += tDataSz;
}
while (tWorkingRecAttr != NULL) {
- tWorkingRecAttr->setNULL();
+ tWorkingRecAttr->setUNDEFINED();
tWorkingRecAttr = tWorkingRecAttr->next();
}
if (hasSomeData)
- return r;
+ {
+ DBUG_RETURN(r);
+ }
}
- return 0;
+ DBUG_RETURN(0);
}
NdbDictionary::Event::TableEvent
@@ -487,10 +537,20 @@ NdbEventOperationImpl::getEventType()
void
NdbEventOperationImpl::print()
{
+ int i;
ndbout << "EventId " << m_eventId << "\n";
- for (int i = 0; i < 2; i++) {
- NdbRecAttr *p = theFirstRecAttrs[i];
+ for (i = 0; i < 2; i++) {
+ NdbRecAttr *p = theFirstPkAttrs[i];
+ ndbout << " %u " << i;
+ while (p) {
+ ndbout << " : " << p->attrId() << " = " << *p;
+ p = p->next();
+ }
+ ndbout << "\n";
+ }
+ for (i = 0; i < 2; i++) {
+ NdbRecAttr *p = theFirstDataAttrs[i];
ndbout << " %u " << i;
while (p) {
ndbout << " : " << p->attrId() << " = " << *p;
@@ -639,23 +699,28 @@ NdbGlobalEventBufferHandle::~NdbGlobalEventBufferHandle()
void
NdbGlobalEventBufferHandle::addBufferId(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBufferHandle::addBufferId");
+ DBUG_PRINT("enter",("bufferId=%d",bufferId));
if (m_nids >= NDB_MAX_ACTIVE_EVENTS) {
ndbout_c("NdbGlobalEventBufferHandle::addBufferId error in paramerer setting");
exit(-1);
}
m_bufferIds[m_nids] = bufferId;
m_nids++;
+ DBUG_VOID_RETURN;
}
void
NdbGlobalEventBufferHandle::dropBufferId(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBufferHandle::dropBufferId");
+ DBUG_PRINT("enter",("bufferId=%d",bufferId));
for (int i = 0; i < m_nids; i++)
if (m_bufferIds[i] == bufferId) {
m_nids--;
for (; i < m_nids; i++)
m_bufferIds[i] = m_bufferIds[i+1];
- return;
+ DBUG_VOID_RETURN;
}
ndbout_c("NdbGlobalEventBufferHandle::dropBufferId %d does not exist",
bufferId);
@@ -674,10 +739,11 @@ NdbGlobalEventBufferHandle::drop(NdbGlobalEventBufferHandle *handle)
}
*/
int
-NdbGlobalEventBufferHandle::prepareAddSubscribeEvent(Uint32 eventId,
- int& hasSubscriber)
+NdbGlobalEventBufferHandle::prepareAddSubscribeEvent
+(NdbEventOperationImpl *eventOp, int& hasSubscriber)
{
- ADD_DROP_LOCK_GUARDR(int,real_prepareAddSubscribeEvent(this, eventId, hasSubscriber));
+ ADD_DROP_LOCK_GUARDR(int,real_prepareAddSubscribeEvent(this, eventOp,
+ hasSubscriber));
}
void
NdbGlobalEventBufferHandle::addSubscribeEvent
@@ -830,57 +896,68 @@ NdbGlobalEventBuffer::~NdbGlobalEventBuffer()
// NdbMem_Deallocate(m_eventBufferIdToEventId);
}
void
-NdbGlobalEventBuffer::real_init (NdbGlobalEventBufferHandle *h,
+NdbGlobalEventBuffer::real_init (NdbGlobalEventBufferHandle *h,
int MAX_NUMBER_ACTIVE_EVENTS)
{
- if (m_handlers.size() == 0) { // First init
+ DBUG_ENTER("NdbGlobalEventBuffer::real_init");
+ DBUG_PRINT("enter",("m_handles.size()=%u %u", m_handlers.size(), h));
+ if (m_handlers.size() == 0)
+ { // First init
+ DBUG_PRINT("info",("first to come"));
m_max = MAX_NUMBER_ACTIVE_EVENTS;
m_buf = new BufItem[m_max];
- // (BufItem *)NdbMem_Allocate(m_max*sizeof(BufItem));
-
for (int i=0; i<m_max; i++) {
- m_buf[i].gId = 0;
+ m_buf[i].gId= 0;
}
}
+ assert(m_max == MAX_NUMBER_ACTIVE_EVENTS);
// TODO make sure we don't hit roof
- // m_handlers[m_nhandlers] = h;
m_handlers.push_back(h);
- // ndbout_c("NdbGlobalEventBuffer::real_init(), m_handles=%u %u", m_nhandlers, h);
+ DBUG_VOID_RETURN;
}
void
NdbGlobalEventBuffer::real_remove(NdbGlobalEventBufferHandle *h)
{
- // ndbout_c("NdbGlobalEventBuffer::real_init_remove(), m_handles=%u %u", m_nhandlers, h);
- for (Uint32 i=0 ; i < m_handlers.size(); i++) {
- // ndbout_c("%u %u %u", i, m_handlers[i], h);
- if (m_handlers[i] == h) {
+ DBUG_ENTER("NdbGlobalEventBuffer::real_remove");
+ DBUG_PRINT("enter",("m_handles.size()=%u %u", m_handlers.size(), h));
+ for (Uint32 i=0 ; i < m_handlers.size(); i++)
+ {
+ DBUG_PRINT("info",("m_handlers[%u] %u", i, m_handlers[i]));
+ if (m_handlers[i] == h)
+ {
m_handlers.erase(i);
- if (m_handlers.size() == 0) {
- // ndbout_c("last to go");
+ if (m_handlers.size() == 0)
+ {
+ DBUG_PRINT("info",("last to go"));
delete[] m_buf;
m_buf = NULL;
- // NdbMem_Free((char*)m_buf);
}
- return;
+ DBUG_VOID_RETURN;
}
}
- ndbout_c("NdbGlobalEventBuffer::real_init_remove() non-existing handle");
- exit(-1);
+ ndbout_c("NdbGlobalEventBuffer::real_remove() non-existing handle");
+ DBUG_PRINT("error",("non-existing handle"));
+ abort();
+ DBUG_VOID_RETURN;
}
-int
+int
NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
-(NdbGlobalEventBufferHandle *aHandle, Uint32 eventId, int& hasSubscriber)
+(NdbGlobalEventBufferHandle *aHandle, NdbEventOperationImpl *eventOp,
+ int& hasSubscriber)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_prepareAddSubscribeEvent");
int i;
- int bufferId = -1;
+ int bufferId= -1;
+ Uint32 eventId= eventOp->m_eventId;
+ DBUG_PRINT("enter",("eventId: %u", eventId));
// add_drop_lock(); // only one thread can do add or drop at a time
// Find place where eventId already set
for (i=0; i<m_no; i++) {
if (m_buf[i].gId == eventId) {
- bufferId = i;
+ bufferId= i;
break;
}
}
@@ -888,53 +965,55 @@ NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
// find space for new bufferId
for (i=0; i<m_no; i++) {
if (m_buf[i].gId == 0) {
- bufferId = i; // we found an empty spot
- break;
+ bufferId= i; // we found an empty spot
+ goto found_bufferId;
}
}
if (bufferId < 0 &&
m_no < m_max) {
// room for more so get that
- bufferId=m_no;
- m_buf[m_no].gId = 0;
+ bufferId= m_no;
+ m_buf[m_no].gId= 0;
m_no++;
} else {
- ndbout_c("prepareAddSubscribeEvent: Can't accept more subscribers");
- // add_drop_unlock();
- return -1;
+ // add_drop_unlock();
+ DBUG_PRINT("error",("Can't accept more subscribers:"
+ " bufferId=%d, m_no=%d, m_max=%d",
+ bufferId, m_no, m_max));
+ DBUG_RETURN(-1);
}
}
+found_bufferId:
- BufItem &b = m_buf[ID(bufferId)];
+ BufItem &b= m_buf[ID(bufferId)];
if (b.gId == 0) { // first subscriber needs some initialization
- bufferId = NO_ID(0, bufferId);
+ bufferId= NO_ID(0, bufferId);
- b.gId = eventId;
+ b.gId= eventId;
+ b.eventType= (Uint32)eventOp->m_eventImpl->mi_type;
- if ((b.p_buf_mutex = NdbMutex_Create()) == NULL) {
+ if ((b.p_buf_mutex= NdbMutex_Create()) == NULL) {
ndbout_c("NdbGlobalEventBuffer: NdbMutex_Create() failed");
- exit(-1);
+ abort();
}
- b.subs = 0;
- b.f = 0;
- b.sz = 0;
- b.max_sz = aHandle->m_bufferL;
- b.data =
+ b.subs= 0;
+ b.f= 0;
+ b.sz= 0;
+ b.max_sz= aHandle->m_bufferL;
+ b.data=
(BufItem::Data *)NdbMem_Allocate(b.max_sz*sizeof(BufItem::Data));
for (int i = 0; i < b.max_sz; i++) {
- b.data[i].sdata = NULL;
- b.data[i].ptr[0].p = NULL;
- b.data[i].ptr[1].p = NULL;
- b.data[i].ptr[2].p = NULL;
+ b.data[i].sdata= NULL;
+ b.data[i].ptr[0].p= NULL;
+ b.data[i].ptr[1].p= NULL;
+ b.data[i].ptr[2].p= NULL;
}
} else {
-#ifdef EVENT_DEBUG
- ndbout_c("NdbGlobalEventBuffer::prepareAddSubscribeEvent: TRYING handle one subscriber per event b.subs = %u", b.subs);
-#endif
-
+ DBUG_PRINT("info",
+ ("TRYING handle one subscriber per event b.subs=%u",b.subs));
int ni = -1;
for(int i=0; i < b.subs;i++) {
if (b.ps[i].theHandle == NULL) {
@@ -946,9 +1025,10 @@ NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
if (b.subs < MAX_SUBSCRIBERS_PER_EVENT) {
ni = b.subs;
} else {
- ndbout_c("prepareAddSubscribeEvent: Can't accept more subscribers");
+ DBUG_PRINT("error",
+ ("Can't accept more subscribers: b.subs=%d",b.subs));
// add_drop_unlock();
- return -1;
+ DBUG_RETURN(-1);
}
}
bufferId = NO_ID(ni, bufferId);
@@ -969,23 +1049,25 @@ NdbGlobalEventBuffer::real_prepareAddSubscribeEvent
else
hasSubscriber = 0;
-#ifdef EVENT_DEBUG
- ndbout_c("prepareAddSubscribeEvent: handed out bufferId %d for eventId %d",
- bufferId, eventId);
-#endif
+ DBUG_PRINT("info",("handed out bufferId=%d for eventId=%d hasSubscriber=%d",
+ bufferId, eventId, hasSubscriber));
/* we now have a lock on the prepare so that no one can mess with this
* unlock comes in unprepareAddSubscribeEvent or addSubscribeEvent
*/
- return bufferId;
+ DBUG_RETURN(bufferId);
}
void
NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
+ DBUG_PRINT("enter", ("bufferId=%d,ID(bufferId)=%d,NO(bufferId)=%d",
+ bufferId, ID(bufferId), NO(bufferId)));
+
b.ps[n].theHandle = NULL;
// remove subscribers from the end,
@@ -998,10 +1080,8 @@ NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent(int bufferId)
break;
if (b.subs == 0) {
-#ifdef EVENT_DEBUG
- ndbout_c("unprepareAddSubscribeEvent: no more subscribers left on eventId %d", b.gId);
-#endif
- b.gId = 0; // We don't have any subscribers, reuse BufItem
+ DBUG_PRINT("info",("no more subscribers left on eventId %d", b.gId));
+ b.gId= 0; // We don't have any subscribers, reuse BufItem
if (b.data) {
NdbMem_Free((void *)b.data);
b.data = NULL;
@@ -1012,12 +1092,14 @@ NdbGlobalEventBuffer::real_unprepareAddSubscribeEvent(int bufferId)
}
}
// add_drop_unlock();
+ DBUG_VOID_RETURN;
}
void
NdbGlobalEventBuffer::real_addSubscribeEvent(int bufferId,
void *ndbEventOperation)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_addSubscribeEvent");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
@@ -1025,9 +1107,8 @@ NdbGlobalEventBuffer::real_addSubscribeEvent(int bufferId,
b.ps[n].theHandle->addBufferId(bufferId);
// add_drop_unlock();
-#ifdef EVENT_DEBUG
- ndbout_c("addSubscribeEvent:: added bufferId %d", bufferId);
-#endif
+ DBUG_PRINT("info",("added bufferId %d", bufferId));
+ DBUG_VOID_RETURN;
}
void
@@ -1040,6 +1121,7 @@ int
NdbGlobalEventBuffer::real_prepareDropSubscribeEvent(int bufferId,
int& hasSubscriber)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_prepareDropSubscribeEvent");
// add_drop_lock(); // only one thread can do add or drop at a time
BufItem &b = m_buf[ID(bufferId)];
@@ -1055,14 +1137,17 @@ NdbGlobalEventBuffer::real_prepareDropSubscribeEvent(int bufferId,
else if (n == 1)
hasSubscriber = 0;
else
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
- return 0;
+ DBUG_RETURN(0);
}
void
NdbGlobalEventBuffer::real_dropSubscribeEvent(int bufferId)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_dropSubscribeEvent");
// add_drop_lock(); // only one thread can do add-drop at a time
BufItem &b = m_buf[ID(bufferId)];
@@ -1078,6 +1163,7 @@ NdbGlobalEventBuffer::real_dropSubscribeEvent(int bufferId)
#ifdef EVENT_DEBUG
ndbout_c("dropSubscribeEvent:: dropped bufferId %d", bufferId);
#endif
+ DBUG_VOID_RETURN;
}
void
@@ -1100,10 +1186,13 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
const SubTableData * const sdata,
LinearSectionPtr ptr[3])
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_insertDataL");
BufItem &b = m_buf[ID(bufferId)];
#ifdef EVENT_DEBUG
int n = NO(bufferId);
#endif
+
+ if ( b.eventType & (1 << (Uint32)sdata->operation) )
{
if (b.subs) {
#ifdef EVENT_DEBUG
@@ -1112,7 +1201,9 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
// move front forward
if (copy_data_alloc(sdata, ptr,
b.data[b.f].sdata, b.data[b.f].ptr))
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
for (int i=0; i < b.subs; i++) {
NdbGlobalEventBuffer::BufItem::Ps &e = b.ps[i];
if (e.theHandle) { // active subscriber
@@ -1120,7 +1211,7 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
if (e.bufferempty == 0) {
e.overrun++; // another item has been overwritten
e.b++; // move next-to-read next since old item was overwritten
- if (e.b == b.max_sz) e.b = 0; // start from beginning
+ if (e.b == b.max_sz) e.b= 0; // start from beginning
}
}
e.bufferempty = 0;
@@ -1140,21 +1231,35 @@ NdbGlobalEventBuffer::real_insertDataL(int bufferId,
#endif
}
}
- return 0;
+ else
+ {
+#ifdef EVENT_DEBUG
+ ndbout_c("skipped");
+#endif
+ }
+
+ DBUG_RETURN(0);
}
int NdbGlobalEventBuffer::hasData(int bufferId) {
+ DBUG_ENTER("NdbGlobalEventBuffer::hasData");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
NdbGlobalEventBuffer::BufItem::Ps &e = b.ps[n];
if(e.bufferempty)
- return 0;
+ {
+ DBUG_RETURN(0);
+ }
if (b.f <= e.b)
- return b.max_sz-e.b + b.f;
+ {
+ DBUG_RETURN(b.max_sz-e.b + b.f);
+ }
else
- return b.f-e.b;
+ {
+ DBUG_RETURN(b.f-e.b);
+ }
}
int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
@@ -1162,6 +1267,7 @@ int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
LinearSectionPtr ptr[3],
int *pOverrun)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_getDataL");
BufItem &b = m_buf[ID(bufferId)];
int n = NO(bufferId);
NdbGlobalEventBuffer::BufItem::Ps &e = b.ps[n];
@@ -1172,13 +1278,20 @@ int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
}
if (e.bufferempty)
- return 0; // nothing to get
+ {
+ DBUG_RETURN(0); // nothing to get
+ }
+
+ DBUG_PRINT("info",("ID(bufferId) %d NO(bufferId) %d e.b %d",
+ ID(bufferId), NO(bufferId), e.b));
if (copy_data_alloc(b.data[e.b].sdata, b.data[e.b].ptr,
sdata, ptr))
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
- e.b++; if (e.b == b.max_sz) e.b = 0; // move next-to-read forward
+ e.b++; if (e.b == b.max_sz) e.b= 0; // move next-to-read forward
if (b.f == e.b) // back has cought up with front
e.bufferempty = 1;
@@ -1187,7 +1300,7 @@ int NdbGlobalEventBuffer::real_getDataL(const int bufferId,
ndbout_c("getting data from buffer %d with eventId %d", bufferId, b.gId);
#endif
- return hasData(bufferId)+1;
+ DBUG_RETURN(hasData(bufferId)+1);
}
int
NdbGlobalEventBuffer::copy_data_alloc(const SubTableData * const f_sdata,
@@ -1195,49 +1308,59 @@ NdbGlobalEventBuffer::copy_data_alloc(const SubTableData * const f_sdata,
SubTableData * &t_sdata,
LinearSectionPtr t_ptr[3])
{
- if (t_sdata == NULL) {
- t_sdata = (SubTableData *)NdbMem_Allocate(sizeof(SubTableData));
- }
+ DBUG_ENTER("NdbGlobalEventBuffer::copy_data_alloc");
+ unsigned sz4= (sizeof(SubTableData)+3)>>2;
+ Uint32 *ptr= (Uint32*)NdbMem_Allocate((sz4 +
+ f_ptr[0].sz +
+ f_ptr[1].sz +
+ f_ptr[2].sz) * sizeof(Uint32));
+ if (t_sdata)
+ NdbMem_Free((char*)t_sdata);
+ t_sdata= (SubTableData *)ptr;
memcpy(t_sdata,f_sdata,sizeof(SubTableData));
+ ptr+= sz4;
+
for (int i = 0; i < 3; i++) {
LinearSectionPtr & f_p = f_ptr[i];
LinearSectionPtr & t_p = t_ptr[i];
if (f_p.sz > 0) {
- if (t_p.p == NULL) {
- t_p.p = (Uint32 *)NdbMem_Allocate(sizeof(Uint32)*f_p.sz);
- } else if (t_p.sz != f_p.sz) {
- NdbMem_Free(t_p.p);
- t_p.p = (Uint32 *)NdbMem_Allocate(sizeof(Uint32)*f_p.sz);
- }
+ t_p.p= (Uint32 *)ptr;
memcpy(t_p.p, f_p.p, sizeof(Uint32)*f_p.sz);
- } else if (t_p.p != NULL) {
- NdbMem_Free(t_p.p);
- t_p.p = NULL;
+ ptr+= f_p.sz;
+ t_p.sz= f_p.sz;
+ } else {
+ t_p.p= NULL;
+ t_p.sz= 0;
}
- t_p.sz = f_p.sz;
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbGlobalEventBuffer::real_wait(NdbGlobalEventBufferHandle *h,
int aMillisecondNumber)
{
+ DBUG_ENTER("NdbGlobalEventBuffer::real_wait");
// check if there are anything in any of the buffers
int i;
int n = 0;
for (i = 0; i < h->m_nids; i++)
n += hasData(h->m_bufferIds[i]);
- if (n) return n;
+ if (n)
+ {
+ DBUG_RETURN(n);
+ }
int r = NdbCondition_WaitTimeout(h->p_cond, ndb_global_event_buffer_mutex,
aMillisecondNumber);
if (r > 0)
- return -1;
+ {
+ DBUG_RETURN(-1);
+ }
n = 0;
for (i = 0; i < h->m_nids; i++)
n += hasData(h->m_bufferIds[i]);
- return n;
+ DBUG_RETURN(n);
}
template class Vector<NdbGlobalEventBufferHandle*>;
diff --git a/ndb/src/ndbapi/NdbEventOperationImpl.hpp b/ndb/src/ndbapi/NdbEventOperationImpl.hpp
index f67c998e639..96958979c76 100644
--- a/ndb/src/ndbapi/NdbEventOperationImpl.hpp
+++ b/ndb/src/ndbapi/NdbEventOperationImpl.hpp
@@ -14,21 +14,13 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbEventOperationImpl.hpp
- * Include:
- * Link:
- * Author: Tomas Ulin MySQL AB
- * Date: 2003-11-21
- * Version: 0.1
- * Description: Event support
- * Documentation:
- * Adjust: 2003-11-21 Tomas Ulin First version.
- ****************************************************************************/
-
#ifndef NdbEventOperationImpl_H
#define NdbEventOperationImpl_H
+#include <NdbEventOperation.hpp>
+#include <signaldata/SumaImpl.hpp>
+#include <transporter/TransporterDefinitions.hpp>
+
class NdbGlobalEventBufferHandle;
class NdbEventOperationImpl : public NdbEventOperation {
public:
@@ -61,12 +53,17 @@ public:
void print();
void printAll();
+ const NdbError & getNdbError() const;
+ NdbError m_error;
+
Ndb *m_ndb;
NdbEventImpl *m_eventImpl;
NdbGlobalEventBufferHandle *m_bufferHandle;
- NdbRecAttr *theFirstRecAttrs[2];
- NdbRecAttr *theCurrentRecAttrs[2];
+ NdbRecAttr *theFirstPkAttrs[2];
+ NdbRecAttr *theCurrentPkAttrs[2];
+ NdbRecAttr *theFirstDataAttrs[2];
+ NdbRecAttr *theCurrentDataAttrs[2];
NdbEventOperation::State m_state;
Uint32 m_eventId;
@@ -84,7 +81,7 @@ public:
//static NdbGlobalEventBufferHandle *init(int MAX_NUMBER_ACTIVE_EVENTS);
// returns bufferId 0-N if ok otherwise -1
- int prepareAddSubscribeEvent(Uint32 eventId, int& hasSubscriber);
+ int prepareAddSubscribeEvent(NdbEventOperationImpl *, int& hasSubscriber);
void unprepareAddSubscribeEvent(int bufferId);
void addSubscribeEvent(int bufferId,
NdbEventOperationImpl *ndbEventOperationImpl);
@@ -138,7 +135,8 @@ private:
int MAX_NUMBER_ACTIVE_EVENTS);
int real_prepareAddSubscribeEvent(NdbGlobalEventBufferHandle *h,
- Uint32 eventId, int& hasSubscriber);
+ NdbEventOperationImpl *,
+ int& hasSubscriber);
void real_unprepareAddSubscribeEvent(int bufferId);
void real_addSubscribeEvent(int bufferId, void *ndbEventOperation);
@@ -182,6 +180,7 @@ private:
// local mutex for each event/buffer
NdbMutex *p_buf_mutex;
Uint32 gId;
+ Uint32 eventType;
struct Data {
SubTableData *sdata;
LinearSectionPtr ptr[3];
diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp
index aa918a6f9f8..c668533457d 100644
--- a/ndb/src/ndbapi/NdbImpl.hpp
+++ b/ndb/src/ndbapi/NdbImpl.hpp
@@ -75,6 +75,17 @@ public:
int m_optimized_node_selection;
+ BaseString m_dbname; // Database name
+ BaseString m_schemaname; // Schema name
+
+ BaseString m_prefix; // Buffer for preformatted internal name <db>/<schema>/
+
+ void update_prefix()
+ {
+ m_prefix.assfmt("%s%c%s%c", m_dbname.c_str(), table_name_separator,
+ m_schemaname.c_str(), table_name_separator);
+ }
+
/**
* NOTE free lists must be _after_ theNdbObjectIdMap take
* assure that destructors are run in correct order
@@ -92,7 +103,7 @@ public:
Ndb_free_list_t<NdbIndexScanOperation> theScanOpIdleList;
Ndb_free_list_t<NdbOperation> theOpIdleList;
Ndb_free_list_t<NdbIndexOperation> theIndexOpIdleList;
- Ndb_free_list_t<NdbConnection> theConIdleList;
+ Ndb_free_list_t<NdbTransaction> theConIdleList;
};
#ifdef VM_TRACE
@@ -123,9 +134,9 @@ Ndb::void2rec(void* val){
}
inline
-NdbConnection *
+NdbTransaction *
Ndb::void2con(void* val){
- return (NdbConnection*)val;
+ return (NdbTransaction*)val;
}
inline
@@ -141,7 +152,7 @@ Ndb::void2rec_iop(void* val){
}
inline
-NdbConnection *
+NdbTransaction *
NdbReceiver::getTransaction(){
return ((NdbOperation*)m_owner)->theNdbCon;
}
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index 39da9c5f5d0..853bab09c41 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -16,9 +16,8 @@
#include <ndb_global.h>
#include <NdbIndexOperation.hpp>
-#include <NdbResultSet.hpp>
#include <Ndb.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include "NdbApiSignal.hpp"
#include <AttributeHeader.hpp>
#include <signaldata/TcIndx.hpp>
@@ -27,10 +26,8 @@
#include <signaldata/IndxAttrInfo.hpp>
NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
- NdbOperation(aNdb),
- m_theIndex(NULL),
- m_theIndexLen(0),
- m_theNoOfIndexDefined(0)
+ NdbOperation(aNdb, NdbOperation::UniqueIndexAccess),
+ m_theIndex(NULL)
{
m_tcReqGSN = GSN_TCINDXREQ;
m_attrInfoGSN = GSN_INDXATTRINFO;
@@ -56,7 +53,7 @@ NdbIndexOperation::~NdbIndexOperation()
int
NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
const NdbTableImpl * aTable,
- NdbConnection* myConnection)
+ NdbTransaction* myConnection)
{
NdbOperation::init(aTable, myConnection);
@@ -64,25 +61,13 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
case(NdbDictionary::Index::UniqueHashIndex):
break;
case(NdbDictionary::Index::Undefined):
- case(NdbDictionary::Index::HashIndex):
- case(NdbDictionary::Index::UniqueOrderedIndex):
case(NdbDictionary::Index::OrderedIndex):
setErrorCodeAbort(4003);
return -1;
}
m_theIndex = anIndex;
- m_thePrimaryTable = aTable;
m_accessTable = anIndex->m_table;
- m_theIndexLen = 0;
- m_theNoOfIndexDefined = 0;
- for (Uint32 i=0; i<NDB_MAX_ATTRIBUTES_IN_INDEX; i++)
- for (int j=0; j<3; j++)
- m_theIndexDefined[i][j] = false;
-
- TcIndxReq * const tcIndxReq = CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
- tcIndxReq->scanInfo = 0;
- theKEYINFOptr = &tcIndxReq->keyInfo[0];
- theATTRINFOptr = &tcIndxReq->attrInfo[0];
+ theNoOfTupKeyLeft = m_accessTable->getNoOfPrimaryKeys();
return 0;
}
@@ -179,310 +164,10 @@ int NdbIndexOperation::interpretedDeleteTuple()
return NdbOperation::interpretedDeleteTuple();
}
-int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
+const NdbDictionary::Index*
+NdbIndexOperation::getIndex() const
{
- register Uint32 tAttrId;
-
- Uint32 tData;
- Uint32 tKeyInfoPosition;
- const char* aValue = aValuePassed;
- Uint32 xfrmData[1024];
- Uint32 tempData[1024];
-
- if ((theStatus == OperationDefined) &&
- (aValue != NULL) &&
- (tAttrInfo != NULL )) {
- /************************************************************************
- * Start by checking that the attribute is an index key.
- * This value is also the word order in the tuple key of this
- * tuple key attribute.
- * Then check that this tuple key has not already been defined.
- * Finally check if all tuple key attributes have been defined. If
- * this is true then set Operation state to tuple key defined.
- ************************************************************************/
- tAttrId = tAttrInfo->m_attrId;
- tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
- Uint32 i = 0;
-
- // Check that the attribute is part if the index attributes
- // by checking if it is a primary key attribute of index table
- if (tAttrInfo->m_pk) {
- Uint32 tKeyDefined = theTupleKeyDefined[0][2];
- Uint32 tKeyAttrId = theTupleKeyDefined[0][0];
- do {
- if (tKeyDefined == false) {
- goto keyEntryFound;
- } else {
- if (tKeyAttrId != tAttrId) {
- /******************************************************************
- * We read the key defined variable in advance.
- * It could potentially read outside its area when
- * i = MAXNROFTUPLEKEY - 1,
- * it is not a problem as long as the variable
- * theTupleKeyDefined is defined
- * in the middle of the object.
- * Reading wrong data and not using it causes no problems.
- *****************************************************************/
- i++;
- tKeyAttrId = theTupleKeyDefined[i][0];
- tKeyDefined = theTupleKeyDefined[i][2];
- continue;
- } else {
- goto equal_error2;
- }//if
- }//if
- } while (i < NDB_MAX_ATTRIBUTES_IN_INDEX);
- goto equal_error2;
- } else {
- goto equal_error1;
- }
- /**************************************************************************
- * Now it is time to retrieve the tuple key data from the pointer supplied
- * by the application.
- * We have to retrieve the size of the attribute in words and bits.
- *************************************************************************/
- keyEntryFound:
- m_theIndexDefined[i][0] = tAttrId;
- m_theIndexDefined[i][1] = tKeyInfoPosition;
- m_theIndexDefined[i][2] = true;
-
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
- {
- /*************************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte
- * boundary. If so only assign the pointer to the internal variable
- * aValue. If it is not aligned then we start by copying the value to
- * tempData and use this as aValue instead.
- *************************************************************************/
- const int attributeSize = sizeInBytes;
- const int slack = sizeInBytes & 3;
- if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
- memcpy(&tempData[0], aValue, attributeSize);
- aValue = (char*)&tempData[0];
- if(slack != 0) {
- char * tmp = (char*)&tempData[0];
- memset(&tmp[attributeSize], 0, (4 - slack));
- }//if
- }//if
- }
- const char* aValueToWrite = aValue;
-
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- if (cs != 0) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply <= 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
-
- Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
- Uint32 totalSizeInWords = (sizeInBytes + 3)/4;// Inc. bits in last word
- Uint32 sizeInWords = sizeInBytes / 4; // Exc. bits in last word
-
- if (true){ //tArraySize != 0) {
- Uint32 tIndexLen = m_theIndexLen;
-
- m_theIndexLen = tIndexLen + totalSizeInWords;
- if ((aVariableKeyLen == sizeInBytes) ||
- (aVariableKeyLen == 0)) {
- ;
- } else {
- goto equal_error3;
- }
- }
-#if 0
- else {
- /************************************************************************
- * The attribute is a variable array. We need to use the length parameter
- * to know the size of this attribute in the key information and
- * variable area. A key is however not allowed to be larger than 4
- * kBytes and this is checked for variable array attributes
- * used as keys.
- ***********************************************************************/
- Uint32 tMaxVariableKeyLenInWord = (MAXTUPLEKEYLENOFATTERIBUTEINWORD -
- tKeyInfoPosition);
- tAttrSizeInBits = aVariableKeyLen << 3;
- tAttrSizeInWords = tAttrSizeInBits >> 5;
- tAttrBitsInLastWord = tAttrSizeInBits - (tAttrSizeInWords << 5);
- tAttrLenInWords = ((tAttrSizeInBits + 31) >> 5);
- if (tAttrLenInWords > tMaxVariableKeyLenInWord) {
- setErrorCodeAbort(4207);
- return -1;
- }//if
- m_theIndexLen = m_theIndexLen + tAttrLenInWords;
- }//if
-#endif
- int tDistrKey = tAttrInfo->m_distributionKey;
- int tDistrGroup = tAttrInfo->m_distributionGroup;
- OperationType tOpType = theOperationType;
- if ((tDistrKey != 1) && (tDistrGroup != 1)) {
- ;
- } else if (tDistrKey == 1) {
- theDistrKeySize += totalSizeInWords;
- theDistrKeyIndicator = 1;
- } else {
- Uint32 TsizeInBytes = sizeInBytes;
- Uint32 TbyteOrderFix = 0;
- char* TcharByteOrderFix = (char*)&TbyteOrderFix;
- if (tAttrInfo->m_distributionGroupBits == 8) {
- char tFirstChar = aValue[TsizeInBytes - 2];
- char tSecondChar = aValue[TsizeInBytes - 2];
- TcharByteOrderFix[0] = tFirstChar;
- TcharByteOrderFix[1] = tSecondChar;
- TcharByteOrderFix[2] = 0x30;
- TcharByteOrderFix[3] = 0x30;
- theDistrGroupType = 0;
- } else {
- TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10)
- + (aValue[TsizeInBytes - 1] - 0x30);
- theDistrGroupType = 1;
- }//if
- theDistributionGroup = TbyteOrderFix;
- theDistrGroupIndicator = 1;
- }//if
- /**************************************************************************
- * If the operation is a write request and the attribute is stored then
- * we also set the value in the stored part through putting the
- * information in the INDXATTRINFO signals.
- *************************************************************************/
- if ((tOpType == WriteRequest)) {
- if (!tAttrInfo->m_indexOnly){
- int dummy_error;
- // invalid data can crash kernel
- if (cs != NULL &&
- (*cs->cset->well_formed_len)(cs,
- aValueToWrite,
- aValueToWrite + sizeInBytes,
- sizeInBytes,
- &dummy_error) != sizeInBytes)
- goto equal_error4;
- Uint32 ahValue;
- Uint32 sz = totalSizeInWords;
- /*
- * XXX should be linked in metadata but cannot now because
- * things can be defined in arbitrary order
- */
- const NdbColumnImpl* primaryCol = m_thePrimaryTable->getColumn(tAttrInfo->m_name.c_str());
- assert(primaryCol != NULL);
- AttributeHeader::init(&ahValue, primaryCol->m_attrId, sz);
- insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
- if (bitsInLastWord != 0) {
- tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
- tData = convertEndian(tData);
- tData = tData & ((1 << bitsInLastWord) - 1);
- tData = convertEndian(tData);
- insertATTRINFO( tData );
- }//if
- }//if
- }//if
- /**************************************************************************
- * Store the Key information in the TCINDXREQ and INDXKEYINFO signals.
- *************************************************************************/
- if (insertKEYINFO(aValue, tKeyInfoPosition,
- totalSizeInWords, bitsInLastWord) != -1) {
- /************************************************************************
- * Add one to number of tuple key attributes defined.
- * If all have been defined then set the operation state to indicate
- * that tuple key is defined.
- * Thereby no more search conditions are allowed in this version.
- ***********************************************************************/
- Uint32 tNoIndexDef = m_theNoOfIndexDefined;
- Uint32 tErrorLine = theErrorLine;
- int tNoIndexAttrs = m_theIndex->m_columns.size();
- unsigned char tInterpretInd = theInterpretIndicator;
- tNoIndexDef++;
- m_theNoOfIndexDefined = tNoIndexDef;
- tErrorLine++;
- theErrorLine = tErrorLine;
- if (int(tNoIndexDef) == tNoIndexAttrs) {
- if (tOpType == UpdateRequest) {
- if (tInterpretInd == 1) {
- theStatus = GetValue;
- } else {
- theStatus = SetValue;
- }//if
- return 0;
- } else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
- (tOpType == ReadExclusive)) {
- theStatus = GetValue;
- // create blob handles automatically
- if (tOpType == 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 (getBlobHandle(theNdbCon, c) == NULL)
- return -1;
- }
- }
- }
- return 0;
- } else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
- theStatus = SetValue;
- return 0;
- } else {
- setErrorCodeAbort(4005);
- return -1;
- }//if
- }//if
- return 0;
- } else {
-
- return -1;
- }//if
- } else {
- if (theStatus != OperationDefined) {
- return -1;
- }//if
-
- if (aValue == NULL) {
- setErrorCodeAbort(4505);
- return -1;
- }//if
-
- if ( tAttrInfo == NULL ) {
- setErrorCodeAbort(4004);
- return -1;
- }//if
- }//if
- return -1;
-
- equal_error1:
- setErrorCodeAbort(4205);
- return -1;
-
- equal_error2:
- setErrorCodeAbort(4206);
- return -1;
-
- equal_error3:
- setErrorCodeAbort(4209);
- return -1;
-
- equal_error4:
- setErrorCodeAbort(744);
- return -1;
-}
-
-int NdbIndexOperation::executeCursor(int aProcessorId)
-{
- printf("NdbIndexOperation::executeCursor NYI\n");
- // NYI
- return -1;
-}
-void
-NdbIndexOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
-{
- TcIndxReq * const req = CAST_PTR(TcIndxReq, signal->getDataPtrSend());
- TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
+ return m_theIndex;
}
int
@@ -525,18 +210,18 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
// We start by filling in the first 8 unconditional words of the
// TCINDXREQ signal.
//-------------------------------------------------------------
- TcIndxReq * const tcIndxReq =
- CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
+ TcKeyReq * tcKeyReq =
+ CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
Uint32 tIndexId = m_theIndex->m_indexId;
Uint32 tSchemaVersion = m_theIndex->m_version;
- tcIndxReq->apiConnectPtr = aTC_ConnectPtr;
- tcIndxReq->senderData = ptr2int();
- tcIndxReq->attrLen = tTotalCurrAI_Len;
- tcIndxReq->indexId = tIndexId;
- tcIndxReq->indexSchemaVersion = tSchemaVersion;
+ tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
+ tcKeyReq->senderData = ptr2int();
+ tcKeyReq->attrLen = tTotalCurrAI_Len;
+ tcKeyReq->tableId = tIndexId;
+ tcKeyReq->tableSchemaVersion = tSchemaVersion;
tTransId1 = (Uint32) aTransactionId;
tTransId2 = (Uint32) (aTransactionId >> 32);
@@ -564,59 +249,53 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
Uint8 tSimpleState = tReadInd & tSimpleAlt;
//theNdbCon->theSimpleState = tSimpleState;
- tcIndxReq->transId1 = tTransId1;
- tcIndxReq->transId2 = tTransId2;
+ tcKeyReq->transId1 = tTransId1;
+ tcKeyReq->transId2 = tTransId2;
tReqInfo = 0;
- if (tTotalCurrAI_Len <= TcIndxReq::MaxAttrInfo) {
- tcIndxReq->setAIInTcIndxReq(tReqInfo, tTotalCurrAI_Len);
+ if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
} else {
- tcIndxReq->setAIInTcIndxReq(tReqInfo, TcIndxReq::MaxAttrInfo);
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
}//if
- tcIndxReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
- tcIndxReq->setCommitFlag(tReqInfo, tCommitIndicator);
- tcIndxReq->setStartFlag(tReqInfo, tStartIndicator);
+ tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
+ tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
+ tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
const Uint8 tInterpretIndicator = theInterpretIndicator;
- tcIndxReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+ tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
Uint8 tDirtyIndicator = theDirtyIndicator;
OperationType tOperationType = theOperationType;
- Uint32 tIndexLen = m_theIndexLen;
+ Uint32 tIndexLen = theTupKeyLen;
Uint8 abortOption = theNdbCon->m_abortOption;
- tcIndxReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
- tcIndxReq->setOperationType(tReqInfo, tOperationType);
- tcIndxReq->setIndexLength(tReqInfo, tIndexLen);
- tcIndxReq->setCommitType(tReqInfo, abortOption);
+ tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
+ tcKeyReq->setOperationType(tReqInfo, tOperationType);
+ tcKeyReq->setKeyLength(tReqInfo, tIndexLen);
+ tcKeyReq->setAbortOption(tReqInfo, abortOption);
- Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
- Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
- Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
Uint8 tScanIndicator = theScanInfo & 1;
- tcIndxReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
- tcIndxReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
- tcIndxReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
- tcIndxReq->setScanIndFlag(tReqInfo, tScanIndicator);
+ tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
+ tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
- tcIndxReq->requestInfo = tReqInfo;
+ tcKeyReq->requestInfo = tReqInfo;
//-------------------------------------------------------------
// The next step is to fill in the upto three conditional words.
//-------------------------------------------------------------
- Uint32* tOptionalDataPtr = &tcIndxReq->scanInfo;
+ Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
Uint32 tDistrGHIndex = tScanIndicator;
- Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
Uint32 tScanInfo = theScanInfo;
- Uint32 tDistributionGroup = theDistributionGroup;
- Uint32 tDistrKeySize = theDistrKeySize;
+ Uint32 tDistrKey = theDistributionKey;
tOptionalDataPtr[0] = tScanInfo;
- tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
- tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
//-------------------------------------------------------------
// The next is step is to compress the key data part of the
@@ -624,10 +303,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
- Uint32 Tdata1 = tcIndxReq->keyInfo[0];
- Uint32 Tdata2 = tcIndxReq->keyInfo[1];
- Uint32 Tdata3 = tcIndxReq->keyInfo[2];
- Uint32 Tdata4 = tcIndxReq->keyInfo[3];
+ Uint32 Tdata1 = tcKeyReq->keyInfo[0];
+ Uint32 Tdata2 = tcKeyReq->keyInfo[1];
+ Uint32 Tdata3 = tcKeyReq->keyInfo[2];
+ Uint32 Tdata4 = tcKeyReq->keyInfo[3];
Uint32 Tdata5;
tKeyDataPtr[0] = Tdata1;
@@ -635,10 +314,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
tKeyDataPtr[2] = Tdata3;
tKeyDataPtr[3] = Tdata4;
if (tIndexLen > 4) {
- Tdata1 = tcIndxReq->keyInfo[4];
- Tdata2 = tcIndxReq->keyInfo[5];
- Tdata3 = tcIndxReq->keyInfo[6];
- Tdata4 = tcIndxReq->keyInfo[7];
+ Tdata1 = tcKeyReq->keyInfo[4];
+ Tdata2 = tcKeyReq->keyInfo[5];
+ Tdata3 = tcKeyReq->keyInfo[6];
+ Tdata4 = tcKeyReq->keyInfo[7];
tKeyDataPtr[4] = Tdata1;
tKeyDataPtr[5] = Tdata2;
@@ -652,12 +331,12 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint32 tAttrInfoIndex;
- if (tIndexLen > TcIndxReq::MaxKeyInfo) {
+ if (tIndexLen > TcKeyReq::MaxKeyInfo) {
/**
* Set transid and TC connect ptr in the INDXKEYINFO signals
*/
- NdbApiSignal* tSignal = theFirstKEYINFO;
- Uint32 remainingKey = tIndexLen - TcIndxReq::MaxKeyInfo;
+ NdbApiSignal* tSignal = theTCREQ->next();
+ Uint32 remainingKey = tIndexLen - TcKeyReq::MaxKeyInfo;
do {
Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -678,7 +357,7 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
}
tSignal = tnextSignal;
} while (tSignal != NULL);
- tAttrInfoIndex = tKeyIndex + TcIndxReq::MaxKeyInfo;
+ tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
} else {
tAttrInfoIndex = tKeyIndex + tIndexLen;
}//if
@@ -688,14 +367,14 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
// above.
//-------------------------------------------------------------
Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
- Tdata1 = tcIndxReq->attrInfo[0];
- Tdata2 = tcIndxReq->attrInfo[1];
- Tdata3 = tcIndxReq->attrInfo[2];
- Tdata4 = tcIndxReq->attrInfo[3];
- Tdata5 = tcIndxReq->attrInfo[4];
-
- theTCREQ->setLength(tcIndxReq->getAIInTcIndxReq(tReqInfo) +
- tAttrInfoIndex + TcIndxReq::StaticLength);
+ Tdata1 = tcKeyReq->attrInfo[0];
+ Tdata2 = tcKeyReq->attrInfo[1];
+ Tdata3 = tcKeyReq->attrInfo[2];
+ Tdata4 = tcKeyReq->attrInfo[3];
+ Tdata5 = tcKeyReq->attrInfo[4];
+
+ theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
+ tAttrInfoIndex + TcKeyReq::StaticLength);
tAIDataPtr[0] = Tdata1;
tAIDataPtr[1] = Tdata2;
tAIDataPtr[2] = Tdata3;
@@ -724,11 +403,6 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
return 0;
}
-void NdbIndexOperation::closeScan()
-{
- printf("NdbIndexOperation::closeScan NYI\n");
-}
-
/***************************************************************************
int receiveTCINDXREF( NdbApiSignal* aSignal)
@@ -740,17 +414,5 @@ Remark: Handles the reception of the TCKEYREF signal.
int
NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal)
{
- const TcIndxRef * const tcIndxRef = CAST_CONSTPTR(TcIndxRef, aSignal->getDataPtr());
-
- if (checkState_TransId(aSignal) == -1) {
- return -1;
- }//if
-
- theStatus = Finished;
-
- theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
- Uint32 errorCode = tcIndxRef->errorCode;
- theError.code = errorCode;
- theNdbCon->setOperationErrorCodeAbort(errorCode);
- return theNdbCon->OpCompleteFailure(theNdbCon->m_abortOption);
+ return receiveTCKEYREF(aSignal);
}//NdbIndexOperation::receiveTCINDXREF()
diff --git a/ndb/src/ndbapi/NdbLinHash.hpp b/ndb/src/ndbapi/NdbLinHash.hpp
index f245a261a04..0655e81ce9d 100644
--- a/ndb/src/ndbapi/NdbLinHash.hpp
+++ b/ndb/src/ndbapi/NdbLinHash.hpp
@@ -192,7 +192,7 @@ template <class C>
inline
Int32
NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data )
-{
+{
const Uint32 hash = Hash(str, len);
int dir, seg;
getBucket(hash, &dir, &seg);
@@ -219,8 +219,9 @@ NdbLinHash<C>::insertKey( const char* str, Uint32 len, Uint32 lkey1, C* data )
chain->localkey1 = lkey1;
chain->next = 0;
chain->theData = data;
+ len++; // Null terminated
chain->str = new Uint32[((len + 3) >> 2)];
- memcpy( &chain->str[0], str, len );
+ memcpy( &chain->str[0], str, len);
if (oldChain != 0)
oldChain->next = chain;
else
@@ -426,19 +427,26 @@ NdbLinHash<C>::getNext(NdbElement_t<C> * curr){
return curr->next;
int dir = 0, seg = 0;
-
- if(curr != 0){
+ int counts;
+ if(curr != 0)
+ {
getBucket(curr->hash, &dir, &seg);
+ counts = seg + 1;
+ }
+ else
+ {
+ counts = 0;
}
for(int countd = dir; countd < DIRECTORYSIZE;countd++ ){
if (directory[countd] != 0) {
- for(int counts = seg + 1; counts < SEGMENTSIZE; counts++ ){
+ for(; counts < SEGMENTSIZE; counts++ ){
if (directory[countd]->elements[counts] != 0) {
return directory[countd]->elements[counts];
}
}
}
+ counts = 0;
}
return 0;
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index 88d8a000d50..ca08c39e070 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
#include "NdbRecAttr.hpp"
@@ -37,7 +37,8 @@
* aTable: Pointers to the Table object
* Remark: Creat an object of NdbOperation.
****************************************************************************/
-NdbOperation::NdbOperation(Ndb* aNdb) :
+NdbOperation::NdbOperation(Ndb* aNdb, NdbOperation::Type aType) :
+ m_type(aType),
theReceiver(aNdb),
theErrorLine(0),
theNdb(aNdb),
@@ -49,7 +50,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
theCurrentATTRINFO(NULL),
theTotalCurrAI_Len(0),
theAI_LenInCurrAI(0),
- theFirstKEYINFO(NULL),
theLastKEYINFO(NULL),
theFirstLabel(NULL),
@@ -68,13 +68,11 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
//theSchemaVersion(0),
theTotalNrOfKeyWordInSignal(8),
theTupKeyLen(0),
- theNoOfTupKeyDefined(0),
+ theNoOfTupKeyLeft(0),
theOperationType(NotDefined),
theStatus(Init),
theMagicNumber(0xFE11D0),
theScanInfo(0),
- theDistrKeySize(0),
- theDistributionGroup(0),
m_tcReqGSN(GSN_TCKEYREQ),
m_keyInfoGSN(GSN_KEYINFO),
m_attrInfoGSN(GSN_ATTRINFO),
@@ -131,7 +129,7 @@ NdbOperation::setErrorCodeAbort(int anErrorCode)
*****************************************************************************/
int
-NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
+NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection){
NdbApiSignal* tSignal;
theStatus = Init;
theError.code = 0;
@@ -145,14 +143,11 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
- theFirstKEYINFO = NULL;
theLastKEYINFO = NULL;
- theTupKeyLen = 0;
- theNoOfTupKeyDefined = 0;
- theDistrKeySize = 0;
- theDistributionGroup = 0;
+ theTupKeyLen = 0;
+ theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();
theTotalCurrAI_Len = 0;
theAI_LenInCurrAI = 0;
@@ -161,9 +156,7 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theSimpleIndicator = 0;
theDirtyIndicator = 0;
theInterpretIndicator = 0;
- theDistrGroupIndicator= 0;
- theDistrGroupType = 0;
- theDistrKeyIndicator = 0;
+ theDistrKeyIndicator_ = 0;
theScanInfo = 0;
theTotalNrOfKeyWordInSignal = 8;
theMagicNumber = 0xABCDEF01;
@@ -210,11 +203,16 @@ NdbOperation::release()
NdbBlob* tBlob;
NdbBlob* tSaveBlob;
- if (theTCREQ != NULL)
+ tSignal = theTCREQ;
+ while (tSignal != NULL)
{
- theNdb->releaseSignal(theTCREQ);
- }
+ tSaveSignal = tSignal;
+ tSignal = tSignal->next();
+ theNdb->releaseSignal(tSaveSignal);
+ }
theTCREQ = NULL;
+ theLastKEYINFO = NULL;
+
tSignal = theFirstATTRINFO;
while (tSignal != NULL)
{
@@ -224,15 +222,7 @@ NdbOperation::release()
}
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
- tSignal = theFirstKEYINFO;
- while (tSignal != NULL)
- {
- tSaveSignal = tSignal;
- tSignal = tSignal->next();
- theNdb->releaseSignal(tSaveSignal);
- }
- theFirstKEYINFO = NULL;
- theLastKEYINFO = NULL;
+
if (theInterpretIndicator == 1)
{
tBranch = theFirstBranch;
@@ -403,3 +393,9 @@ NdbOperation::getTableName() const
{
return m_currentTable->m_externalName.c_str();
}
+
+const NdbDictionary::Table*
+NdbOperation::getTable() const
+{
+ return m_currentTable;
+}
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index dfc54133e6c..835e33dfb40 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -14,28 +14,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*****************************************************************************
- * Name: NdbOperationDefine.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 "NdbOperation.hpp"
+#include <ndb_global.h>
+#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
-#include "NdbConnection.hpp"
-#include "Ndb.hpp"
-#include "NdbRecAttr.hpp"
+#include <NdbTransaction.hpp>
+#include <Ndb.hpp>
+#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
#include "NdbOut.hpp"
#include "NdbImpl.hpp"
#include <NdbIndexScanOperation.hpp>
-#include "NdbBlob.hpp"
+#include <NdbBlob.hpp>
#include <Interpreter.hpp>
@@ -48,7 +37,7 @@
int
NdbOperation::insertTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -68,7 +57,7 @@ NdbOperation::insertTuple()
int
NdbOperation::updateTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -88,7 +77,7 @@ NdbOperation::updateTuple()
int
NdbOperation::writeTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -128,7 +117,7 @@ NdbOperation::readTuple(NdbOperation::LockMode lm)
int
NdbOperation::readTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -149,7 +138,7 @@ NdbOperation::readTuple()
int
NdbOperation::deleteTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -170,7 +159,7 @@ NdbOperation::deleteTuple()
int
NdbOperation::readTupleExclusive()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -247,7 +236,7 @@ NdbOperation::committedRead()
int
NdbOperation::dirtyUpdate()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -270,7 +259,7 @@ NdbOperation::dirtyUpdate()
int
NdbOperation::dirtyWrite()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -293,7 +282,7 @@ NdbOperation::dirtyWrite()
int
NdbOperation::interpretedUpdateTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -316,7 +305,7 @@ NdbOperation::interpretedUpdateTuple()
int
NdbOperation::interpretedDeleteTuple()
{
- NdbConnection* tNdbCon = theNdbCon;
+ NdbTransaction* tNdbCon = theNdbCon;
int tErrorLine = theErrorLine;
if (theStatus == Init) {
theStatus = OperationDefined;
@@ -350,7 +339,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
{
NdbRecAttr* tRecAttr;
if ((tAttrInfo != NULL) &&
- (!tAttrInfo->m_indexOnly) &&
(theStatus != Init)){
if (theStatus != GetValue) {
if (theInterpretIndicator == 1) {
@@ -398,10 +386,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
setErrorCodeAbort(4004);
return NULL;
}//if
- if (tAttrInfo->m_indexOnly){
- setErrorCodeAbort(4208);
- return NULL;
- }//if
}//if
setErrorCodeAbort(4200);
return NULL;
@@ -422,6 +406,14 @@ int
NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
const char* aValuePassed, Uint32 len)
{
+ DBUG_ENTER("NdbOperation::setValue");
+ DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
+ tAttrInfo->m_name.c_str(),
+ theOperationType,
+ aValuePassed, len));
+ if (aValuePassed != NULL)
+ DBUG_DUMP("value", (char*)aValuePassed, len);
+
int tReturnCode;
Uint32 tAttrId;
Uint32 tData;
@@ -437,7 +429,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
;
} else {
setErrorCodeAbort(4234);
- return -1;
+ DBUG_RETURN(-1);
}//if
} else {
if (tStatus == GetValue) {
@@ -448,7 +440,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
// to set values in the tuple by setValue.
//--------------------------------------------------------------------
if (insertATTRINFO(Interpreter::EXIT_OK) == -1){
- return -1;
+ DBUG_RETURN(-1);
}
theInterpretedSize = theTotalCurrAI_Len -
(theInitialReadSize + 5);
@@ -459,47 +451,47 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
// setValue used in the wrong context. Application coding error.
//-------------------------------------------------------------------
setErrorCodeAbort(4234); //Wrong error code
- return -1;
+ DBUG_RETURN(-1);
}//if
theStatus = SetValueInterpreted;
}//if
} else if (tOpType == InsertRequest) {
if ((theStatus != SetValue) && (theStatus != OperationDefined)) {
setErrorCodeAbort(4234);
- return -1;
+ DBUG_RETURN(-1);
}//if
} else if (tOpType == ReadRequest || tOpType == ReadExclusive) {
setErrorCodeAbort(4504);
- return -1;
+ DBUG_RETURN(-1);
} else if (tOpType == DeleteRequest) {
setErrorCodeAbort(4504);
- return -1;
+ DBUG_RETURN(-1);
} else if (tOpType == OpenScanRequest || tOpType == OpenRangeScanRequest) {
setErrorCodeAbort(4228);
- return -1;
+ DBUG_RETURN(-1);
} else {
//---------------------------------------------------------------------
// setValue with undefined operation type.
// Probably application coding error.
//---------------------------------------------------------------------
setErrorCodeAbort(4108);
- return -1;
+ DBUG_RETURN(-1);
}//if
if (tAttrInfo == NULL) {
setErrorCodeAbort(4004);
- return -1;
+ DBUG_RETURN(-1);
}//if
if (tAttrInfo->m_pk) {
if (theOperationType == InsertRequest) {
- return equal_impl(tAttrInfo, aValuePassed, len);
+ DBUG_RETURN(equal_impl(tAttrInfo, aValuePassed, len));
} else {
setErrorCodeAbort(4202);
- return -1;
+ DBUG_RETURN(-1);
}//if
}//if
if (len > 8000) {
setErrorCodeAbort(4216);
- return -1;
+ DBUG_RETURN(-1);
}//if
tAttrId = tAttrInfo->m_attrId;
@@ -512,33 +504,19 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
insertATTRINFO(ahValue);
// Insert Attribute Id with the value
// NULL into ATTRINFO part.
- return 0;
+ DBUG_RETURN(0);
} else {
/***********************************************************************
* Setting a NULL value on a NOT NULL attribute is not allowed.
**********************************************************************/
setErrorCodeAbort(4203);
- return -1;
+ DBUG_RETURN(-1);
}//if
}//if
// Insert Attribute Id into ATTRINFO part.
const Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- int dummy_error;
- // invalid data can crash kernel
- if (cs != NULL &&
- // fast fix bug#7340
- tAttrInfo->m_type != NdbDictionary::Column::Text &&
- (*cs->cset->well_formed_len)(cs,
- aValue,
- aValue + sizeInBytes,
- sizeInBytes,
- &dummy_error) != sizeInBytes) {
- setErrorCodeAbort(744);
- return -1;
- }
#if 0
tAttrSize = tAttrInfo->theAttrSize;
tArraySize = tAttrInfo->theArraySize;
@@ -552,7 +530,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
const Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
if (len != sizeInBytes && (len != 0)) {
setErrorCodeAbort(4209);
- return -1;
+ DBUG_RETURN(-1);
}//if
const Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Including bits in last word
const Uint32 sizeInWords = sizeInBytes / 4; // Excluding bits in last word
@@ -580,7 +558,7 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
tReturnCode = insertATTRINFOloop((Uint32*)aValue, sizeInWords);
if (tReturnCode == -1) {
- return tReturnCode;
+ DBUG_RETURN(tReturnCode);
}//if
if (bitsInLastWord != 0) {
tData = *(Uint32*)(aValue + sizeInWords*4);
@@ -589,15 +567,15 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
tData = convertEndian(tData);
tReturnCode = insertATTRINFO(tData);
if (tReturnCode == -1) {
- return tReturnCode;
+ DBUG_RETURN(tReturnCode);
}//if
}//if
theErrorLine++;
- return 0;
+ DBUG_RETURN(0);
}//NdbOperation::setValue()
NdbBlob*
-NdbOperation::getBlobHandle(NdbConnection* aCon, const NdbColumnImpl* tAttrInfo)
+NdbOperation::getBlobHandle(NdbTransaction* aCon, const NdbColumnImpl* tAttrInfo)
{
NdbBlob* tBlob = theBlobList;
NdbBlob* tLastBlob = NULL;
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index 48882a479b9..58a816e3c1a 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -16,7 +16,7 @@
#include <ndb_global.h>
#include <NdbOperation.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include "NdbApiSignal.hpp"
#include <Ndb.hpp>
#include <NdbRecAttr.hpp>
@@ -65,7 +65,7 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
if (tReturnCode == -1) {
return -1;
}
- NdbApiSignal *tSignal = theFirstKEYINFO;
+ NdbApiSignal *tSignal = theTCREQ->next();
while (tSignal != NULL) {
NdbApiSignal* tnextSignal = tSignal->next();
tReturnCode = tp->sendSignal(tSignal, aNodeId);
@@ -208,13 +208,9 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
abortOption = tSimpleIndicator ? AO_IgnoreError : abortOption;
tcKeyReq->setAbortOption(tReqInfo, abortOption);
- Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
- Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
- Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
Uint8 tScanIndicator = theScanInfo & 1;
- tcKeyReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
- tcKeyReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
@@ -225,15 +221,13 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
//-------------------------------------------------------------
Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
Uint32 tDistrGHIndex = tScanIndicator;
- Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
Uint32 tScanInfo = theScanInfo;
- Uint32 tDistributionGroup = theDistributionGroup;
- Uint32 tDistrKeySize = theDistrKeySize;
+ Uint32 tDistrKey = theDistributionKey;
tOptionalDataPtr[0] = tScanInfo;
- tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
- tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
//-------------------------------------------------------------
// The next is step is to compress the key data part of the
@@ -273,7 +267,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
/**
* Set transid, TC connect ptr and length in the KEYINFO signals
*/
- NdbApiSignal* tSignal = theFirstKEYINFO;
+ NdbApiSignal* tSignal = theTCREQ->next();
Uint32 remainingKey = tTupKeyLen - TcKeyReq::MaxKeyInfo;
do {
Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -555,10 +549,11 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
theStatus = Finished;
// blobs want this
if (m_abortOption != AO_IgnoreError)
- theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
-
+ {
+ theNdbCon->theReturnStatus = NdbTransaction::ReturnFailure;
+ }
theError.code = aSignal->readData(4);
- theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), m_abortOption);
+ theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), ao);
if(theOperationType != ReadRequest || !theSimpleIndicator) // not simple read
return theNdbCon->OpCompleteFailure(ao, m_abortOption != AO_IgnoreError);
diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp
index ace90e35ca4..41e0cb1d140 100644
--- a/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -14,13 +14,12 @@
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 <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <Ndb.hpp>
-#include "NdbRecAttr.hpp"
+#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
#include "Interpreter.hpp"
#include <NdbIndexScanOperation.hpp>
@@ -84,7 +83,7 @@ NdbOperation::incCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -136,7 +135,7 @@ NdbOperation::write_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -184,7 +183,7 @@ NdbOperation::read_attrCheck(const NdbColumnImpl* tNdbColumnImpl)
}
return tNdbColumnImpl->m_attrId;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -220,7 +219,7 @@ NdbOperation::initial_interpreterCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -246,7 +245,7 @@ NdbOperation::labelCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -266,7 +265,7 @@ NdbOperation::intermediate_interpreterCheck()
}
return 0;
} else {
- if (theNdbCon->theCommitStatus == NdbConnection::Started)
+ if (theNdbCon->theCommitStatus == NdbTransaction::Started)
setErrorCodeAbort(4200);
}
return -1;
@@ -1012,33 +1011,56 @@ NdbOperation::insertCall(Uint32 aCall)
int
NdbOperation::branch_col(Uint32 type,
- Uint32 ColId, const char * val, Uint32 len,
+ Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
+ DBUG_ENTER("NdbOperation::branch_col");
+ DBUG_PRINT("enter", ("type=%u col=%u val=0x%x len=%u label=%u",
+ type, ColId, val, len, Label));
+ if (val != NULL)
+ DBUG_DUMP("value", (char*)val, len);
+
if (initial_interpreterCheck() == -1)
- return -1;
+ DBUG_RETURN(-1);
Interpreter::BinaryCondition c = (Interpreter::BinaryCondition)type;
-
- const NdbDictionary::Column * col =
+
+ const NdbColumnImpl * col =
m_currentTable->getColumn(ColId);
if(col == 0){
abort();
}
- Uint32 vc = col->getType() == NdbDictionary::Column::Varchar;
- Uint32 colLen = col->getLength() + 2 * vc;
- Uint32 al = (4 - (colLen & 3)) & 0x3;
-
- if (insertATTRINFO(Interpreter::BranchCol(c, al, vc, nopad)) == -1)
- return -1;
+ if (val == NULL)
+ len = 0;
+ else {
+ if (! col->getStringType()) {
+ // prevent assert in NdbSqlUtil on length error
+ Uint32 sizeInBytes = col->m_attrSize * col->m_arraySize;
+ if (len != 0 && len != sizeInBytes)
+ {
+ setErrorCodeAbort(4209);
+ DBUG_RETURN(-1);
+ }
+ len = sizeInBytes;
+ }
+ }
+
+ Uint32 tempData[2000];
+ if (((UintPtr)val & 3) != 0) {
+ memcpy(tempData, val, len);
+ val = tempData;
+ }
+
+ if (insertATTRINFO(Interpreter::BranchCol(c, 0, 0, false)) == -1)
+ DBUG_RETURN(-1);
if (insertBranch(Label) == -1)
- return -1;
+ DBUG_RETURN(-1);
if (insertATTRINFO(Interpreter::BranchCol_2(ColId, len)))
- return -1;
+ DBUG_RETURN(-1);
Uint32 len2 = Interpreter::mod4(len);
if(len2 == len){
@@ -1049,64 +1071,64 @@ NdbOperation::branch_col(Uint32 type,
Uint32 tmp = 0;
for (Uint32 i = 0; i < len-len2; i++) {
char* p = (char*)&tmp;
- p[i] = val[len2+i];
+ p[i] = ((char*)val)[len2+i];
}
insertATTRINFO(tmp);
}
theErrorLine++;
- return 0;
+ DBUG_RETURN(0);
}
int
-NdbOperation::branch_col_eq(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_eq(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_eq %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::EQ, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_ne(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_ne(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_ne %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::NE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_lt(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_lt(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_lt %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::LT, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_le(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_le(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_le %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::LE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_gt(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_gt(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_gt %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::GT, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_ge(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_ge(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_ge %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::GE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_like(Uint32 ColId, const char * val, Uint32 len,
+NdbOperation::branch_col_like(Uint32 ColId, const void * val, Uint32 len,
bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_like %u %.*s(%u,%d) -> %u", ColId, len, val, len, nopad, Label));
return branch_col(Interpreter::LIKE, ColId, val, len, nopad, Label);
}
int
-NdbOperation::branch_col_notlike(Uint32 ColId, const char * val, Uint32 len,
- bool nopad, Uint32 Label){
+NdbOperation::branch_col_notlike(Uint32 ColId, const void * val, Uint32 len,
+ bool nopad, Uint32 Label){
INT_DEBUG(("branch_col_notlike %u %.*s(%u,%d) -> %u", ColId,len,val,len,nopad,Label));
return branch_col(Interpreter::NOT_LIKE, ColId, val, len, nopad, Label);
}
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index 97b2393e5ed..4be7ccb313c 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -31,14 +31,16 @@ Adjust: 971022 UABMNST First version.
#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <Ndb.hpp>
#include "NdbImpl.hpp"
#include <NdbOut.hpp>
#include <AttributeHeader.hpp>
#include <signaldata/TcKeyReq.hpp>
+#include <signaldata/KeyInfo.hpp>
#include "NdbDictionaryImpl.hpp"
+#include <md5_hash.hpp>
/******************************************************************************
CondIdType equal(const char* anAttrName, char* aValue, Uint32 aVarKeylen);
@@ -55,13 +57,21 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
const char* aValuePassed,
Uint32 aVariableKeyLen)
{
- register Uint32 tAttrId;
+ DBUG_ENTER("NdbOperation::equal_impl");
+ DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
+ tAttrInfo->m_name.c_str(),
+ theOperationType,
+ aValuePassed, aVariableKeyLen));
+ if (aValuePassed != NULL)
+ DBUG_DUMP("value", (char*)aValuePassed, aVariableKeyLen);
+ register Uint32 tAttrId;
+
Uint32 tData;
Uint32 tKeyInfoPosition;
const char* aValue = aValuePassed;
- Uint32 xfrmData[1024];
- Uint32 tempData[1024];
+ Uint64 tempData[512];
+ Uint64 tempData2[512];
if ((theStatus == OperationDefined) &&
(aValue != NULL) &&
@@ -76,6 +86,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
*****************************************************************************/
tAttrId = tAttrInfo->m_attrId;
tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
+ bool tDistrKey = tAttrInfo->m_distributionKey;
+
Uint32 i = 0;
if (tAttrInfo->m_pk) {
Uint32 tKeyDefined = theTupleKeyDefined[0][2];
@@ -117,44 +129,42 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
theTupleKeyDefined[i][1] = tKeyInfoPosition;
theTupleKeyDefined[i][2] = true;
+ OperationType tOpType = theOperationType;
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+
+ Uint32 real_len;
+ if (! tAttrInfo->get_var_length(aValue, real_len)) {
+ setErrorCodeAbort(4209);
+ DBUG_RETURN(-1);
+ }
+
+ // 5.0 fixed storage + NdbBlob uses full size => pad var* with nulls
+ if (real_len < sizeInBytes && m_currentTable->m_noOfBlobs != 0) {
+ memcpy(tempData2, aValue, real_len);
+ memset((char*)tempData2 + real_len, 0, sizeInBytes - real_len);
+ aValue = (char*)tempData2;
+ }
+
{
- /***************************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte
- * boundary. If so only assign the pointer to the internal variable
- * aValue. If it is not aligned then we start by copying the value to
- * tempData and use this as aValue instead.
- *****************************************************************************/
+ /************************************************************************
+ * Check if the pointer of the value passed is aligned on a 4 byte
+ * boundary. If so only assign the pointer to the internal variable
+ * aValue. If it is not aligned then we start by copying the value to
+ * tempData and use this as aValue instead.
+ ***********************************************************************/
const int attributeSize = sizeInBytes;
const int slack = sizeInBytes & 3;
-
- if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
+ const int align = UintPtr(aValue) & 7;
+
+ if (((align & 3) != 0) || (slack != 0) || (tDistrKey && (align != 0)))
+ {
+ ((Uint32*)tempData)[attributeSize >> 2] = 0;
memcpy(&tempData[0], aValue, attributeSize);
aValue = (char*)&tempData[0];
- if(slack != 0) {
- char * tmp = (char*)&tempData[0];
- memset(&tmp[attributeSize], 0, (4 - slack));
- }//if
}//if
}
- const char* aValueToWrite = aValue;
-
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- if (cs != 0) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply <= 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
- Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
- Uint32 sizeInWords = sizeInBytes / 4; // Exc. bits in last word
if (true){ //tArraySize != 0) {
Uint32 tTupKeyLen = theTupKeyLen;
@@ -190,93 +200,58 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
}//if
#endif
- int tDistrKey = tAttrInfo->m_distributionKey;
- int tDistrGroup = tAttrInfo->m_distributionGroup;
- OperationType tOpType = theOperationType;
- if ((tDistrKey != 1) && (tDistrGroup != 1)) {
- ;
- } else if (tDistrKey == 1) {
- theDistrKeySize += totalSizeInWords;
- theDistrKeyIndicator = 1;
- } else {
- Uint32 TsizeInBytes = sizeInBytes;
- Uint32 TbyteOrderFix = 0;
- char* TcharByteOrderFix = (char*)&TbyteOrderFix;
- if (tAttrInfo->m_distributionGroupBits == 8) {
- char tFirstChar = aValue[TsizeInBytes - 2];
- char tSecondChar = aValue[TsizeInBytes - 2];
- TcharByteOrderFix[0] = tFirstChar;
- TcharByteOrderFix[1] = tSecondChar;
- TcharByteOrderFix[2] = 0x30;
- TcharByteOrderFix[3] = 0x30;
- theDistrGroupType = 0;
- } else {
- TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10)
- + (aValue[TsizeInBytes - 1] - 0x30);
- theDistrGroupType = 1;
- }//if
- theDistributionGroup = TbyteOrderFix;
- theDistrGroupIndicator = 1;
- }//if
- /******************************************************************************
+ /**************************************************************************
* If the operation is an insert request and the attribute is stored then
* we also set the value in the stored part through putting the
* information in the ATTRINFO signals.
- *****************************************************************************/
+ *************************************************************************/
if ((tOpType == InsertRequest) ||
(tOpType == WriteRequest)) {
- if (!tAttrInfo->m_indexOnly){
- int dummy_error;
- // invalid data can crash kernel
- if (cs != NULL &&
- (*cs->cset->well_formed_len)(cs,
- aValueToWrite,
- aValueToWrite + sizeInBytes,
- sizeInBytes,
- &dummy_error) != sizeInBytes)
- goto equal_error4;
- Uint32 ahValue;
- const Uint32 sz = totalSizeInWords;
+ Uint32 ahValue;
+ const Uint32 sz = totalSizeInWords;
+
+ // XXX
+ if(m_accessTable == m_currentTable)
+ {
AttributeHeader::init(&ahValue, tAttrId, sz);
- insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
- if (bitsInLastWord != 0) {
- tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
- tData = convertEndian(tData);
- tData = tData & ((1 << bitsInLastWord) - 1);
- tData = convertEndian(tData);
- insertATTRINFO( tData );
- }//if
- }//if
+ }
+ else
+ {
+ assert(m_accessTable->m_index);
+ int attr_id_current_table =
+ m_accessTable->m_index->m_columns[tAttrId]->m_keyInfoPos;
+ AttributeHeader::init(&ahValue, attr_id_current_table, sz);
+ }
+
+ insertATTRINFO( ahValue );
+ insertATTRINFOloop((Uint32*)aValue, sz);
}//if
- /***************************************************************************
+ /**************************************************************************
* Store the Key information in the TCKEYREQ and KEYINFO signals.
- **************************************************************************/
- if (insertKEYINFO(aValue, tKeyInfoPosition,
- totalSizeInWords, bitsInLastWord) != -1) {
- /*************************************************************************
+ *************************************************************************/
+ if (insertKEYINFO(aValue, tKeyInfoPosition, totalSizeInWords) != -1) {
+ /************************************************************************
* Add one to number of tuple key attributes defined.
* If all have been defined then set the operation state to indicate
* that tuple key is defined.
* Thereby no more search conditions are allowed in this version.
- ************************************************************************/
- Uint32 tNoKeysDef = theNoOfTupKeyDefined;
+ ***********************************************************************/
+ Uint32 tNoKeysDef = theNoOfTupKeyLeft - 1;
Uint32 tErrorLine = theErrorLine;
- int tNoTableKeys = m_currentTable->m_noOfKeys;
unsigned char tInterpretInd = theInterpretIndicator;
- tNoKeysDef++;
- theNoOfTupKeyDefined = tNoKeysDef;
+ theNoOfTupKeyLeft = tNoKeysDef;
tErrorLine++;
theErrorLine = tErrorLine;
- if (int(tNoKeysDef) == tNoTableKeys) {
+
+ if (tNoKeysDef == 0) {
if (tOpType == UpdateRequest) {
if (tInterpretInd == 1) {
theStatus = GetValue;
} else {
theStatus = SetValue;
}//if
- return 0;
+ DBUG_RETURN(0);
} else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
(tOpType == ReadExclusive)) {
theStatus = GetValue;
@@ -287,89 +262,62 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
assert(c != 0);
if (c->getBlobType()) {
if (getBlobHandle(theNdbCon, c) == NULL)
- return -1;
+ DBUG_RETURN(-1);
}
}
}
- return 0;
+ DBUG_RETURN(0);
} else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
theStatus = SetValue;
- return 0;
+ DBUG_RETURN(0);
} else {
setErrorCodeAbort(4005);
- return -1;
+ DBUG_RETURN(-1);
}//if
+ DBUG_RETURN(0);
}//if
- return 0;
} else {
- return -1;
+ DBUG_RETURN(-1);
}//if
+ DBUG_RETURN(0);
}
-
+
if (aValue == NULL) {
// NULL value in primary key
setErrorCodeAbort(4505);
- return -1;
+ DBUG_RETURN(-1);
}//if
if ( tAttrInfo == NULL ) {
// Attribute name not found in table
setErrorCodeAbort(4004);
- return -1;
+ DBUG_RETURN(-1);
}//if
if (theStatus == GetValue || theStatus == SetValue){
// All pk's defined
setErrorCodeAbort(4225);
- return -1;
+ DBUG_RETURN(-1);
}//if
+
+ ndbout_c("theStatus: %d", theStatus);
// If we come here, set a general errorcode
// and exit
setErrorCodeAbort(4200);
- return -1;
+ DBUG_RETURN(-1);
equal_error1:
setErrorCodeAbort(4205);
- return -1;
+ DBUG_RETURN(-1);
equal_error2:
setErrorCodeAbort(4206);
- return -1;
+ DBUG_RETURN(-1);
equal_error3:
setErrorCodeAbort(4209);
- return -1;
-
- equal_error4:
- setErrorCodeAbort(744);
- return -1;
-}
-
-/******************************************************************************
- * Uint64 setTupleId( void )
- *
- * Return Value: Return > 0: OK
- * Return 0 : setTupleId failed
- * Parameters:
- * Remark:
- *****************************************************************************/
-Uint64
-NdbOperation::setTupleId()
-{
- if (theStatus != OperationDefined)
- {
- return 0;
- }
- Uint64 tTupleId = theNdb->getTupleIdFromNdb(m_currentTable->m_tableId);
- if (tTupleId == ~(Uint64)0){
- setErrorCodeAbort(theNdb->theError.code);
- return 0;
- }
- if (equal((Uint32)0, tTupleId) == -1)
- return 0;
-
- return tTupleId;
+ DBUG_RETURN(-1);
}
/******************************************************************************
@@ -389,8 +337,7 @@ NdbOperation::setTupleId()
int
NdbOperation::insertKEYINFO(const char* aValue,
register Uint32 aStartPosition,
- register Uint32 anAttrSizeInWords,
- register Uint32 anAttrBitsInLastWord)
+ register Uint32 anAttrSizeInWords)
{
NdbApiSignal* tSignal;
NdbApiSignal* tCurrentKEYINFO;
@@ -410,7 +357,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
*****************************************************************************/
tEndPos = aStartPosition + anAttrSizeInWords - 1;
- if ((tEndPos < 9) && (anAttrBitsInLastWord == 0)) {
+ if ((tEndPos < 9)) {
register Uint32 tkeyData = *(Uint32*)aValue;
//TcKeyReq* tcKeyReq = CAST_PTR(TcKeyReq, tTCREQ->getDataPtrSend());
register Uint32* tDataPtr = (Uint32*)aValue;
@@ -451,10 +398,11 @@ NdbOperation::insertKEYINFO(const char* aValue,
setErrorCodeAbort(4001);
return -1;
}
- if (theFirstKEYINFO != NULL)
+ if (theTCREQ->next() != NULL)
theLastKEYINFO->next(tSignal);
else
- theFirstKEYINFO = tSignal;
+ theTCREQ->next(tSignal);
+
theLastKEYINFO = tSignal;
theLastKEYINFO->next(NULL);
theTotalNrOfKeyWordInSignal += 20;
@@ -467,7 +415,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
* this is the first word in a KEYINFO signal. *
*****************************************************************************/
tPosition = aStartPosition;
- tCurrentKEYINFO = theFirstKEYINFO;
+ tCurrentKEYINFO = theTCREQ->next();
/*****************************************************************************
* Start by filling up Key information in the 8 words allocated in the *
@@ -520,39 +468,20 @@ NdbOperation::insertKEYINFO(const char* aValue,
} while (1);
LastWordLabel:
-
-/*****************************************************************************
- * There could be a last word that only contains partial data. This word*
- * will contain zeroes in the rest of the bits since the index expects *
- * a certain number of words and do not care for parts of words. *
- *****************************************************************************/
- if (anAttrBitsInLastWord != 0) {
- tData = *(Uint32*)(aValue + (anAttrSizeInWords - 1) * 4);
- tData = convertEndian(tData);
- tData = tData & ((1 << anAttrBitsInLastWord) - 1);
- tData = convertEndian(tData);
- if (tPosition > 8) {
- tCurrentKEYINFO->setData(tData, signalCounter);
- signalCounter++;
- } else {
- theTCREQ->setData(tData, (12 + tPosition));
- }//if
- }//if
-
return 0;
}
int
NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
{
- assert(m_accessTable != 0 && m_accessTable->m_sizeOfKeysInWords != 0);
- assert(m_accessTable->m_sizeOfKeysInWords == size);
+ assert(m_accessTable != 0 && m_accessTable->m_keyLenInWords != 0);
+ assert(m_accessTable->m_keyLenInWords == size);
unsigned pos = 0;
while (pos < 8 && pos < size) {
data[pos] = theKEYINFOptr[pos];
pos++;
}
- NdbApiSignal* tSignal = theFirstKEYINFO;
+ NdbApiSignal* tSignal = theTCREQ->next();
unsigned n = 0;
while (pos < size) {
if (n == 20) {
@@ -563,3 +492,115 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
}
return 0;
}
+
+int
+NdbOperation::handle_distribution_key(const Uint64* value, Uint32 len)
+{
+ if(theDistrKeyIndicator_ == 1 ||
+ (theNoOfTupKeyLeft > 0 && m_accessTable->m_noOfDistributionKeys > 1))
+ {
+ return 0;
+ }
+
+ if(m_accessTable->m_noOfDistributionKeys == 1)
+ {
+ setPartitionHash(value, len);
+ }
+ else if(theTCREQ->readSignalNumber() == GSN_TCKEYREQ)
+ {
+ // No support for combined distribution key and scan
+
+ /**
+ * Copy distribution key to linear memory
+ */
+ NdbColumnImpl* const * cols = m_accessTable->m_columns.getBase();
+ Uint32 len = 0;
+ Uint64 tmp[1000];
+
+ Uint32 chunk = 8;
+ Uint32* dst = (Uint32*)tmp;
+ NdbApiSignal* tSignal = theTCREQ;
+ Uint32* src = ((TcKeyReq*)tSignal->getDataPtrSend())->keyInfo;
+ if(tSignal->readSignalNumber() == GSN_SCAN_TABREQ)
+ {
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ chunk = KeyInfo::DataLength;
+ }
+
+ for(unsigned i = m_accessTable->m_columns.size(); i>0; cols++, i--)
+ {
+ if (!(* cols)->getPrimaryKey())
+ continue;
+
+ NdbColumnImpl* tAttrInfo = * cols;
+ Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ Uint32 currLen = (sizeInBytes + 3) >> 2;
+ if (tAttrInfo->getDistributionKey())
+ {
+ while (currLen >= chunk)
+ {
+ memcpy(dst, src, 4*chunk);
+ dst += chunk;
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ currLen -= chunk;
+ chunk = KeyInfo::DataLength;
+ }
+
+ memcpy(dst, src, 4*currLen);
+ dst += currLen;
+ src += currLen;
+ chunk -= currLen;
+ }
+ else
+ {
+ while (currLen >= chunk)
+ {
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ currLen -= chunk;
+ chunk = KeyInfo::DataLength;
+ }
+
+ src += currLen;
+ chunk -= currLen;
+ }
+ }
+ setPartitionHash(tmp, dst - (Uint32*)tmp);
+ }
+ return 0;
+}
+
+void
+NdbOperation::setPartitionHash(Uint32 value)
+{
+ union {
+ Uint32 tmp32;
+ Uint64 tmp64;
+ };
+
+ tmp32 = value;
+ setPartitionHash(&tmp64, 1);
+}
+
+void
+NdbOperation::setPartitionHash(const Uint64* value, Uint32 len)
+{
+ Uint32 buf[4];
+ md5_hash(buf, value, len);
+ setPartitionId(buf[1]);
+}
+
+void
+NdbOperation::setPartitionId(Uint32 value)
+{
+ theDistributionKey = value;
+ theDistrKeyIndicator_ = 1;
+}
+
+Uint32
+NdbOperation::getPartitionId() const
+{
+ return theDistributionKey;
+}
diff --git a/ndb/src/ndbapi/NdbPool.cpp b/ndb/src/ndbapi/NdbPool.cpp
index ba58520c1dc..a8263f564f1 100644
--- a/ndb/src/ndbapi/NdbPool.cpp
+++ b/ndb/src/ndbapi/NdbPool.cpp
@@ -21,14 +21,16 @@
static NdbPool* m_pool = 0;
bool
-create_instance(Uint32 max_ndb_objects,
+create_instance(Ndb_cluster_connection* cc,
+ Uint32 max_ndb_objects,
Uint32 no_conn_obj,
Uint32 init_no_ndb_objects)
{
if (m_pool != NULL) {
return false;
}
- m_pool = NdbPool::create_instance(max_ndb_objects,
+ m_pool = NdbPool::create_instance(cc,
+ max_ndb_objects,
no_conn_obj,
init_no_ndb_objects);
if (m_pool == NULL) {
diff --git a/ndb/src/ndbapi/NdbPoolImpl.cpp b/ndb/src/ndbapi/NdbPoolImpl.cpp
index 131edc74246..32e0a6f1410 100644
--- a/ndb/src/ndbapi/NdbPoolImpl.cpp
+++ b/ndb/src/ndbapi/NdbPoolImpl.cpp
@@ -20,7 +20,8 @@ NdbMutex *NdbPool::pool_mutex = NULL;
NdbPool *the_pool = NULL;
NdbPool*
-NdbPool::create_instance(Uint32 max_ndb_obj,
+NdbPool::create_instance(Ndb_cluster_connection* cc,
+ Uint32 max_ndb_obj,
Uint32 no_conn_obj,
Uint32 init_no_ndb_objects)
{
@@ -32,7 +33,7 @@ NdbPool::create_instance(Uint32 max_ndb_obj,
if (the_pool != NULL) {
a_pool = NULL;
} else {
- the_pool = new NdbPool(max_ndb_obj, no_conn_obj);
+ the_pool = new NdbPool(cc, max_ndb_obj, no_conn_obj);
if (!the_pool->init(init_no_ndb_objects)) {
delete the_pool;
the_pool = NULL;
@@ -76,7 +77,8 @@ NdbPool::initPoolMutex()
return ret_result;
}
-NdbPool::NdbPool(Uint32 max_no_objects,
+NdbPool::NdbPool(Ndb_cluster_connection* cc,
+ Uint32 max_no_objects,
Uint32 no_conn_objects)
{
if (no_conn_objects > 1024) {
@@ -101,6 +103,7 @@ NdbPool::NdbPool(Uint32 max_no_objects,
m_output_queue = 0;
m_input_queue = 0;
m_signal_count = 0;
+ m_cluster_connection = cc;
}
NdbPool::~NdbPool()
@@ -294,9 +297,9 @@ NdbPool::allocate_ndb(Uint32 &id,
return false;
}
if (a_schema_name) {
- a_ndb = new Ndb(a_schema_name, a_catalog_name);
+ a_ndb = new Ndb(m_cluster_connection, a_schema_name, a_catalog_name);
} else {
- a_ndb = new Ndb("");
+ a_ndb = new Ndb(m_cluster_connection, "");
}
if (a_ndb == NULL) {
return false;
diff --git a/ndb/src/ndbapi/NdbPoolImpl.hpp b/ndb/src/ndbapi/NdbPoolImpl.hpp
index af6cf4708cf..cd36f30e90b 100644
--- a/ndb/src/ndbapi/NdbPoolImpl.hpp
+++ b/ndb/src/ndbapi/NdbPoolImpl.hpp
@@ -92,7 +92,8 @@ class NdbPool {
Uint16 prev_db_object;
};
public:
- static NdbPool* create_instance(Uint32 max_ndb_objects = 240,
+ static NdbPool* create_instance(Ndb_cluster_connection*,
+ Uint32 max_ndb_objects = 240,
Uint32 no_conn_obj = 4,
Uint32 init_no_ndb_objects = 8);
static void drop_instance();
@@ -104,7 +105,8 @@ class NdbPool {
bool init(Uint32 initial_no_of_ndb_objects = 8);
void release_all();
static bool initPoolMutex();
- NdbPool(Uint32 max_no_of_ndb_objects, Uint32 no_conn_objects);
+ NdbPool(Ndb_cluster_connection*,
+ Uint32 max_no_of_ndb_objects, Uint32 no_conn_objects);
~NdbPool();
/*
We have three lists:
@@ -158,5 +160,7 @@ class NdbPool {
Uint16 m_input_queue;
Uint16 m_output_queue;
Uint16 m_signal_count;
+
+ Ndb_cluster_connection * m_cluster_connection;
};
#endif
diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp
index 26039fb7867..771da56523c 100644
--- a/ndb/src/ndbapi/NdbRecAttr.cpp
+++ b/ndb/src/ndbapi/NdbRecAttr.cpp
@@ -15,17 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/************************************************************************************************
-Name: NdbRecAttr.C
-Include:
-Link:
-Author: UABRONM Mikael Ronström UAB/B/SD
-Date: 971206
-Version: 0.1
-Description: Interface between TIS and NDB
-Documentation:
-Adjust: 971206 UABRONM First version
-************************************************************************************************/
#include <ndb_global.h>
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
@@ -152,6 +141,40 @@ NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
return false;
}
+static void
+ndbrecattr_print_string(NdbOut& out, const char *type,
+ const char *aref, unsigned sz)
+{
+ const unsigned char* ref = (const unsigned char*)aref;
+ int i, len, printable= 1;
+ // trailing zeroes are not printed
+ for (i=sz-1; i >= 0; i--)
+ if (ref[i] == 0) sz--;
+ else break;
+ if (sz == 0) return; // empty
+
+ for (len=0; len < (int)sz && ref[i] != 0; len++)
+ if (printable && !isprint((int)ref[i]))
+ printable= 0;
+
+ if (printable)
+ out.print("%.*s", len, ref);
+ else
+ {
+ out.print("0x");
+ for (i=0; i < len; i++)
+ out.print("%02X", (int)ref[i]);
+ }
+ if (len != (int)sz)
+ {
+ out.print("[");
+ for (i= len+1; ref[i] != 0; i++)
+ out.print("%u]",len-i);
+ assert((int)sz > i);
+ ndbrecattr_print_string(out,type,aref+i,sz-i);
+ }
+}
+
NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
{
if (r.isNULL())
@@ -175,6 +198,9 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
case NdbDictionary::Column::Bigunsigned:
out << r.u_64_value();
break;
+ case NdbDictionary::Column::Bit:
+ out << hex << "H'" << r.u_32_value() << dec;
+ break;
case NdbDictionary::Column::Unsigned:
out << r.u_32_value();
break;
@@ -196,17 +222,28 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
case NdbDictionary::Column::Tinyint:
out << (int) r.char_value();
break;
+ case NdbDictionary::Column::Binary:
+ ndbrecattr_print_string(out,"Binary",r.aRef(),r.arraySize());
+ j = r.arraySize();
+ break;
case NdbDictionary::Column::Char:
- out.print("%.*s", r.arraySize(), r.aRef());
+ ndbrecattr_print_string(out,"Char",r.aRef(),r.arraySize());
j = length;
break;
case NdbDictionary::Column::Varchar:
- {
- short len = ntohs(r.u_short_value());
- out.print("%.*s", len, r.aRef()+2);
- }
- j = length;
- break;
+ {
+ unsigned len = *(const unsigned char*)r.aRef();
+ ndbrecattr_print_string(out,"Varchar", r.aRef()+1,len);
+ j = length;
+ }
+ break;
+ case NdbDictionary::Column::Varbinary:
+ {
+ unsigned len = *(const unsigned char*)r.aRef();
+ ndbrecattr_print_string(out,"Varbinary", r.aRef()+1,len);
+ j = length;
+ }
+ break;
case NdbDictionary::Column::Float:
out << r.float_value();
break;
@@ -225,6 +262,10 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
out.print("%.*s", len, r.aRef());
}
break;
+ case NdbDictionary::Column::Decimal:
+ case NdbDictionary::Column::Decimalunsigned:
+ goto unknown; // TODO
+ break;
// for dates cut-and-paste from field.cc
case NdbDictionary::Column::Datetime:
{
@@ -327,6 +368,14 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r)
j = length;
}
break;
+ case NdbDictionary::Column::Longvarchar:
+ {
+ unsigned len = uint2korr(r.aRef());
+ ndbrecattr_print_string(out,"Longvarchar", r.aRef()+2,len);
+ j = length;
+ }
+ break;
+ unknown:
default: /* no print functions for the rest, just print type */
out << (int) r.getType();
j = length;
diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp
index cad247512b2..62119880076 100644
--- a/ndb/src/ndbapi/NdbReceiver.cpp
+++ b/ndb/src/ndbapi/NdbReceiver.cpp
@@ -20,7 +20,7 @@
#include "NdbDictionaryImpl.hpp"
#include <NdbRecAttr.hpp>
#include <AttributeHeader.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <TransporterFacade.hpp>
#include <signaldata/TcKeyConf.hpp>
@@ -121,7 +121,15 @@ NdbReceiver::calculate_batch_size(Uint32 key_size,
* no more than MAX_SCAN_BATCH_SIZE is sent from all nodes in total per
* batch.
*/
- batch_byte_size= max_batch_byte_size;
+ if (batch_size == 0)
+ {
+ batch_byte_size= max_batch_byte_size;
+ }
+ else
+ {
+ batch_byte_size= batch_size * tot_size;
+ }
+
if (batch_byte_size * parallelism > max_scan_batch_size) {
batch_byte_size= max_scan_batch_size / parallelism;
}
@@ -140,7 +148,10 @@ NdbReceiver::calculate_batch_size(Uint32 key_size,
}
void
-NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
+NdbReceiver::do_get_value(NdbReceiver * org,
+ Uint32 rows,
+ Uint32 key_size,
+ Uint32 range_no){
if(rows > m_defined_rows){
delete[] m_rows;
m_defined_rows = rows;
@@ -155,7 +166,7 @@ NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
key.m_attrSize = 4;
key.m_nullable = true; // So that receive works w.r.t KEYINFO20
}
- m_key_info = key_size;
+ m_hidden_count = (key_size ? 1 : 0) + range_no ;
for(Uint32 i = 0; i<rows; i++){
NdbRecAttr * prev = theCurrentRecAttr;
@@ -167,6 +178,12 @@ NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
return ; // -1
}
+ if(range_no &&
+ !getValue(&NdbColumnImpl::getImpl(* NdbDictionary::Column::RANGE_NO),0))
+ {
+ abort();
+ }
+
NdbRecAttr* tRecAttr = org->theFirstRecAttr;
while(tRecAttr != 0){
if(getValue(&NdbColumnImpl::getImpl(*tRecAttr->m_column), (char*)0) != 0)
@@ -192,14 +209,14 @@ NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size){
return;
}
-void
+NdbRecAttr*
NdbReceiver::copyout(NdbReceiver & dstRec){
- NdbRecAttr* src = m_rows[m_current_row++];
- NdbRecAttr* dst = dstRec.theFirstRecAttr;
- Uint32 tmp = m_key_info;
- if(tmp > 0){
+ NdbRecAttr *src = m_rows[m_current_row++];
+ NdbRecAttr *dst = dstRec.theFirstRecAttr;
+ NdbRecAttr *start = src;
+ Uint32 tmp = m_hidden_count;
+ while(tmp--)
src = src->next();
- }
while(dst){
Uint32 len = ((src->theAttrSize * src->theArraySize)+3)/4;
@@ -207,6 +224,8 @@ NdbReceiver::copyout(NdbReceiver & dstRec){
src = src->next();
dst = dst->next();
}
+
+ return start;
}
int
diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp
deleted file mode 100644
index 780660169b3..00000000000
--- a/ndb/src/ndbapi/NdbResultSet.cpp
+++ /dev/null
@@ -1,114 +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 */
-
-/*****************************************************************************
- * Name: NdbResultSet.cpp
- * Include:
- * Link:
- * Author: UABMASD Martin Sköld INN/V Alzato
- * Date: 2002-04-01
- * Version: 0.1
- * Description: Cursor class
- * Documentation:
- * Adjust: 2002-04-01 UABMASD First version.
- ****************************************************************************/
-
-#include <Ndb.hpp>
-#include <NdbConnection.hpp>
-#include <NdbResultSet.hpp>
-#include <NdbBlob.hpp>
-
-NdbResultSet::NdbResultSet(NdbScanOperation *owner)
-: m_operation(owner)
-{
-}
-
-NdbResultSet::~NdbResultSet()
-{
-}
-
-void NdbResultSet::init()
-{
-}
-
-int NdbResultSet::nextResult(bool fetchAllowed, bool forceSend)
-{
- int res;
- if ((res = m_operation->nextResult(fetchAllowed, forceSend)) == 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(bool forceSend)
-{
- m_operation->closeScan(forceSend, true);
-}
-
-NdbOperation*
-NdbResultSet::lockTuple(){
- return lockTuple(m_operation->m_transConnection);
-}
-
-NdbOperation*
-NdbResultSet::lockTuple(NdbConnection* takeOverTrans){
- return m_operation->takeOverScanOp(NdbOperation::ReadRequest,
- takeOverTrans);
-}
-
-NdbOperation*
-NdbResultSet::updateTuple(){
- return updateTuple(m_operation->m_transConnection);
-}
-
-NdbOperation*
-NdbResultSet::updateTuple(NdbConnection* takeOverTrans){
- return m_operation->takeOverScanOp(NdbOperation::UpdateRequest,
- takeOverTrans);
-}
-
-int
-NdbResultSet::deleteTuple(){
- return deleteTuple(m_operation->m_transConnection);
-}
-
-int
-NdbResultSet::deleteTuple(NdbConnection * takeOverTrans){
- void * res = m_operation->takeOverScanOp(NdbOperation::DeleteRequest,
- takeOverTrans);
- if(res == 0)
- return -1;
- return 0;
-}
-
-int
-NdbResultSet::restart(bool forceSend){
- return m_operation->restart(forceSend);
-}
diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp
index 0c851427ba5..b39fd10fe95 100644
--- a/ndb/src/ndbapi/NdbScanFilter.cpp
+++ b/ndb/src/ndbapi/NdbScanFilter.cpp
@@ -48,11 +48,8 @@ public:
int cond_col(Interpreter::UnaryCondition, Uint32 attrId);
- template<typename T>
- int cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, T value);
-
int cond_col_const(Interpreter::BinaryCondition, Uint32 attrId,
- const char * value, Uint32 len, bool nopad);
+ const void * value, Uint32 len);
};
const Uint32 LabelExit = ~0;
@@ -247,68 +244,7 @@ NdbScanFilter::isfalse(){
typedef int (NdbOperation:: * Branch1)(Uint32, Uint32 label);
-typedef int (NdbOperation:: * Branch2)(Uint32, Uint32, Uint32 label);
-typedef int (NdbOperation:: * StrBranch2)(Uint32, const char*,Uint32,bool,Uint32);
-
-struct tab {
- Branch2 m_branches[5];
-};
-
-static const tab table[] = {
- /**
- * EQ (AND, OR, NAND, NOR)
- */
- { { 0,
- &NdbOperation::branch_ne,
- &NdbOperation::branch_eq,
- &NdbOperation::branch_eq,
- &NdbOperation::branch_ne } }
-
- /**
- * NEQ
- */
- ,{ { 0,
- &NdbOperation::branch_eq,
- &NdbOperation::branch_ne,
- &NdbOperation::branch_ne,
- &NdbOperation::branch_eq } }
-
- /**
- * LT
- */
- ,{ { 0,
- &NdbOperation::branch_le,
- &NdbOperation::branch_gt,
- &NdbOperation::branch_gt,
- &NdbOperation::branch_le } }
-
- /**
- * LE
- */
- ,{ { 0,
- &NdbOperation::branch_lt,
- &NdbOperation::branch_ge,
- &NdbOperation::branch_ge,
- &NdbOperation::branch_lt } }
-
- /**
- * GT
- */
- ,{ { 0,
- &NdbOperation::branch_ge,
- &NdbOperation::branch_lt,
- &NdbOperation::branch_lt,
- &NdbOperation::branch_ge } }
-
- /**
- * GE
- */
- ,{ { 0,
- &NdbOperation::branch_gt,
- &NdbOperation::branch_le,
- &NdbOperation::branch_le,
- &NdbOperation::branch_gt } }
-};
+typedef int (NdbOperation:: * StrBranch2)(Uint32, const void*, Uint32, bool, Uint32);
struct tab2 {
Branch1 m_branches[5];
@@ -334,134 +270,9 @@ static const tab2 table2[] = {
&NdbOperation::branch_col_eq_null } }
};
-const int tab_sz = sizeof(table)/sizeof(table[0]);
const int tab2_sz = sizeof(table2)/sizeof(table2[0]);
int
-matchType(const NdbDictionary::Column * col){
- return 1;
-}
-
-template<typename T> int load_const(NdbOperation* op, T value, Uint32 reg);
-
-template<>
-int
-load_const(NdbOperation* op, Uint32 value, Uint32 reg){
- return op->load_const_u32(reg, value);
-}
-
-template<>
-int
-load_const(NdbOperation* op, Uint64 value, Uint32 reg){
- return op->load_const_u64(reg, value);
-}
-
-template<typename T>
-int
-NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
- Uint32 AttrId, T value){
-
- if(op < 0 || op >= tab_sz){
- m_operation->setErrorCodeAbort(4262);
- return -1;
- }
-
- if(m_current.m_group < NdbScanFilter::AND ||
- m_current.m_group > NdbScanFilter::NOR){
- m_operation->setErrorCodeAbort(4260);
- return -1;
- }
-
- Branch2 branch = table[op].m_branches[m_current.m_group];
- const NdbDictionary::Column * col =
- m_operation->m_currentTable->getColumn(AttrId);
-
- if(col == 0){
- m_operation->setErrorCodeAbort(4261);
- return -1;
- }
-
- if(!matchType(col)){
- /**
- * Code not reached
- */
- return -1;
- }
-
- if(m_latestAttrib != AttrId){
- m_operation->read_attr(&NdbColumnImpl::getImpl(* col), 4);
- m_latestAttrib = AttrId;
- }
-
- load_const<T>(m_operation, value, 5);
- (m_operation->* branch)(4, 5, m_current.m_ownLabel);
-
- return 0;
-}
-
-int
-NdbScanFilter::eq(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::EQ, AttrId, value);
-}
-
-int
-NdbScanFilter::ne(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::NE, AttrId, value);
-}
-
-int
-NdbScanFilter::lt(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::LT, AttrId, value);
-}
-
-int
-NdbScanFilter::le(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::LE, AttrId, value);
-}
-
-int
-NdbScanFilter::gt(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::GT, AttrId, value);
-}
-
-int
-NdbScanFilter::ge(int AttrId, Uint32 value){
- return m_impl.cond_col_const(Interpreter::GE, AttrId, value);
-}
-
-
-int
-NdbScanFilter::eq(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::EQ, AttrId, value);
-}
-
-int
-NdbScanFilter::ne(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::NE, AttrId, value);
-}
-
-int
-NdbScanFilter::lt(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::LT, AttrId, value);
-}
-
-int
-NdbScanFilter::le(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::LE, AttrId, value);
-}
-
-int
-NdbScanFilter::gt(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::GT, AttrId, value);
-}
-
-int
-NdbScanFilter::ge(int AttrId, Uint64 value){
- return m_impl.cond_col_const(Interpreter::GE, AttrId, value);
-}
-
-
-int
NdbScanFilterImpl::cond_col(Interpreter::UnaryCondition op, Uint32 AttrId){
if(op < 0 || op >= tab2_sz){
@@ -570,11 +381,10 @@ static const tab3 table3[] = {
const int tab3_sz = sizeof(table3)/sizeof(table3[0]);
-
int
NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
Uint32 AttrId,
- const char * value, Uint32 len, bool nopad){
+ const void * value, Uint32 len){
if(op < 0 || op >= tab3_sz){
m_operation->setErrorCodeAbort(4260);
return -1;
@@ -595,49 +405,35 @@ NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition op,
return -1;
}
- (m_operation->* branch)(AttrId, value, len, nopad, m_current.m_ownLabel);
- return 0;
-}
-
-int
-NdbScanFilter::eq(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::EQ, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::ne(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::NE, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::lt(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::LT, ColId, val, len, nopad);
+ int ret = (m_operation->* branch)(AttrId, value, len, false, m_current.m_ownLabel);
+ return ret;
}
int
-NdbScanFilter::le(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::LE, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::gt(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::GT, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::ge(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::GE, ColId, val, len, nopad);
-}
-
-int
-NdbScanFilter::like(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::LIKE, ColId, val, len, nopad);
-}
+NdbScanFilter::cmp(BinaryCondition cond, int ColId,
+ const void *val, Uint32 len)
+{
+ switch(cond){
+ case COND_LE:
+ return m_impl.cond_col_const(Interpreter::LE, ColId, val, len);
+ case COND_LT:
+ return m_impl.cond_col_const(Interpreter::LT, ColId, val, len);
+ case COND_GE:
+ return m_impl.cond_col_const(Interpreter::GE, ColId, val, len);
+ case COND_GT:
+ return m_impl.cond_col_const(Interpreter::GT, ColId, val, len);
+ case COND_EQ:
+ return m_impl.cond_col_const(Interpreter::EQ, ColId, val, len);
+ case COND_NE:
+ return m_impl.cond_col_const(Interpreter::NE, ColId, val, len);
+ case COND_LIKE:
+ return m_impl.cond_col_const(Interpreter::LIKE, ColId, val, len);
+ case COND_NOT_LIKE:
+ return m_impl.cond_col_const(Interpreter::NOT_LIKE, ColId, val, len);
+ }
+ return -1;
+}
-int
-NdbScanFilter::notlike(int ColId, const char * val, Uint32 len, bool nopad){
- return m_impl.cond_col_const(Interpreter::NOT_LIKE, ColId, val, len, nopad);
-}
#if 0
int
@@ -778,10 +574,4 @@ main(void){
#endif
template class Vector<NdbScanFilterImpl::State>;
-#if __SUNPRO_CC != 0x560
-#ifndef _FORTEC_
-template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint32);
-template int NdbScanFilterImpl::cond_col_const(Interpreter::BinaryCondition, Uint32 attrId, Uint64);
-#endif
-#endif
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index 0a39651ce28..90e3a63c53d 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -18,11 +18,11 @@
#include <Ndb.hpp>
#include <NdbScanOperation.hpp>
#include <NdbIndexScanOperation.hpp>
-#include <NdbConnection.hpp>
-#include <NdbResultSet.hpp>
+#include <NdbTransaction.hpp>
#include "NdbApiSignal.hpp"
#include <NdbOut.hpp>
#include "NdbDictionaryImpl.hpp"
+#include <NdbBlob.hpp>
#include <NdbRecAttr.hpp>
#include <NdbReceiver.hpp>
@@ -37,9 +37,8 @@
#define DEBUG_NEXT_RESULT 0
-NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
- NdbOperation(aNdb),
- m_resultSet(0),
+NdbScanOperation::NdbScanOperation(Ndb* aNdb, NdbOperation::Type aType) :
+ NdbOperation(aNdb, aType),
m_transConnection(NULL)
{
theParallelism = 0;
@@ -60,24 +59,11 @@ NdbScanOperation::~NdbScanOperation()
theNdb->releaseNdbScanRec(m_receivers[i]);
}
delete[] m_array;
- if (m_resultSet)
- delete m_resultSet;
}
-NdbResultSet*
-NdbScanOperation::getResultSet()
-{
- if (!m_resultSet)
- m_resultSet = new NdbResultSet(this);
-
- return m_resultSet;
-}
-
-
-
void
NdbScanOperation::setErrorCode(int aErrorCode){
- NdbConnection* tmp = theNdbCon;
+ NdbTransaction* tmp = theNdbCon;
theNdbCon = m_transConnection;
NdbOperation::setErrorCode(aErrorCode);
theNdbCon = tmp;
@@ -85,7 +71,7 @@ NdbScanOperation::setErrorCode(int aErrorCode){
void
NdbScanOperation::setErrorCodeAbort(int aErrorCode){
- NdbConnection* tmp = theNdbCon;
+ NdbTransaction* tmp = theNdbCon;
theNdbCon = m_transConnection;
NdbOperation::setErrorCodeAbort(aErrorCode);
theNdbCon = tmp;
@@ -100,18 +86,21 @@ NdbScanOperation::setErrorCodeAbort(int aErrorCode){
* Remark: Initiates operation record after allocation.
*****************************************************************************/
int
-NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
+NdbScanOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection)
{
m_transConnection = myConnection;
//NdbConnection* aScanConnection = theNdb->startTransaction(myConnection);
- NdbConnection* aScanConnection = theNdb->hupp(myConnection);
+ theNdb->theRemainingStartTransactions++; // will be checked in hupp...
+ NdbTransaction* aScanConnection = theNdb->hupp(myConnection);
if (!aScanConnection){
+ theNdb->theRemainingStartTransactions--;
setErrorCodeAbort(theNdb->getNdbError().code);
return -1;
}
// NOTE! The hupped trans becomes the owner of the operation
if(NdbOperation::init(tab, aScanConnection) != 0){
+ theNdb->theRemainingStartTransactions--;
return -1;
}
@@ -120,17 +109,18 @@ NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
theStatus = GetValue;
theOperationType = OpenScanRequest;
theNdbCon->theMagicNumber = 0xFE11DF;
-
+ theNoOfTupKeyLeft = tab->m_noOfDistributionKeys;
+ m_read_range_no = 0;
return 0;
}
-NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
- Uint32 batch,
- Uint32 parallel,
- bool keyinfo)
+int
+NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
+ Uint32 scan_flags,
+ Uint32 parallel,
+ Uint32 batch)
{
- m_ordered = 0;
-
+ m_ordered = m_descending = false;
Uint32 fragCount = m_currentTable->m_fragmentCount;
if (parallel > fragCount || parallel == 0) {
@@ -143,7 +133,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
// 3. theScanOp contains a NdbScanOperation
if (theNdbCon->theScanningOp != NULL){
setErrorCode(4605);
- return 0;
+ return -1;
}
theNdbCon->theScanningOp = this;
@@ -168,14 +158,14 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
break;
default:
setErrorCode(4003);
- return 0;
+ return -1;
}
- m_keyInfo = (keyinfo || lockExcl) ? 1 : 0;
+ m_keyInfo = ((scan_flags & SF_KeyInfo) || lockExcl) ? 1 : 0;
- bool range = false;
- if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex ||
- m_accessTable->m_indexType == NdbDictionary::Index::UniqueOrderedIndex){
+ bool rangeScan = false;
+ if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex)
+ {
if (m_currentTable == m_accessTable){
// Old way of scanning indexes, should not be allowed
m_currentTable = theNdb->theDictionary->
@@ -186,28 +176,37 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
// Modify operation state
theStatus = GetValue;
theOperationType = OpenRangeScanRequest;
- range = true;
+ rangeScan = true;
}
-
- theParallelism = parallel;
+ bool tupScan = (scan_flags & SF_TupScan);
+ if (tupScan && rangeScan)
+ tupScan = false;
+
+ if (rangeScan && (scan_flags & SF_OrderBy))
+ parallel = fragCount;
+
+ theParallelism = parallel;
+
if(fix_receivers(parallel) == -1){
setErrorCodeAbort(4000);
- return 0;
+ return -1;
}
theSCAN_TABREQ = (!theSCAN_TABREQ ? theNdb->getSignal() : theSCAN_TABREQ);
if (theSCAN_TABREQ == NULL) {
setErrorCodeAbort(4000);
- return 0;
+ return -1;
}//if
+ theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ);
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;
+ req->first_batch_size = batch; // Save user specified batch size
Uint32 reqInfo = 0;
ScanTabReq::setParallelism(reqInfo, parallel);
@@ -215,17 +214,19 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
ScanTabReq::setLockMode(reqInfo, lockExcl);
ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
- ScanTabReq::setRangeScanFlag(reqInfo, range);
+ ScanTabReq::setRangeScanFlag(reqInfo, rangeScan);
+ ScanTabReq::setTupScanFlag(reqInfo, tupScan);
req->requestInfo = reqInfo;
Uint64 transId = theNdbCon->getTransactionId();
req->transId1 = (Uint32) transId;
req->transId2 = (Uint32) (transId >> 32);
- NdbApiSignal* tSignal =
- theFirstKEYINFO;
-
- theFirstKEYINFO = (tSignal ? tSignal : tSignal = theNdb->getSignal());
+ NdbApiSignal* tSignal = theSCAN_TABREQ->next();
+ if(!tSignal)
+ {
+ theSCAN_TABREQ->next(tSignal = theNdb->getSignal());
+ }
theLastKEYINFO = tSignal;
tSignal->setSignal(GSN_KEYINFO);
@@ -233,7 +234,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
theTotalNrOfKeyWordInSignal= 0;
getFirstATTRINFOScan();
- return getResultSet();
+ return 0;
}
int
@@ -357,65 +358,11 @@ NdbScanOperation::getFirstATTRINFOScan()
#define FAKE_PTR 2
#define API_PTR 3
-
-/*
- * After setBound() are done, move the accumulated ATTRINFO signals to
- * a separate list. Then continue with normal scan.
- */
-#if 0
-int
-NdbIndexScanOperation::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;
-
- 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++){
- const NdbColumnImpl* key = m_accessTable->m_index->m_columns[i];
- const NdbColumnImpl* col = m_currentTable->getColumn(key->m_keyInfoPos);
- NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1);
- UintPtr newVal = UintPtr(tmp);
- theTupleKeyDefined[i][0] = FAKE_PTR;
- theTupleKeyDefined[i][1] = (newVal & 0xFFFFFFFF);
-#if (SIZEOF_CHARP == 8)
- theTupleKeyDefined[i][2] = (newVal >> 32);
-#endif
- }
- }
- return res;
-}
-#endif
-
#define WAITFOR_SCAN_TIMEOUT 120000
int
NdbScanOperation::executeCursor(int nodeId){
- NdbConnection * tCon = theNdbCon;
+ NdbTransaction * tCon = theNdbCon;
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
@@ -449,7 +396,7 @@ NdbScanOperation::executeCursor(int nodeId){
TRACE_DEBUG("The node is stopping when attempting to start a scan");
setErrorCode(4030);
}//if
- tCon->theCommitStatus = NdbConnection::Aborted;
+ tCon->theCommitStatus = NdbTransaction::Aborted;
}//if
return -1;
}
@@ -457,6 +404,29 @@ NdbScanOperation::executeCursor(int nodeId){
int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
{
+ int res;
+ if ((res = nextResultImpl(fetchAllowed, forceSend)) == 0) {
+ // handle blobs
+ NdbBlob* tBlob = 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_transConnection->executePendingBlobOps() == -1)
+ return -1;
+ return 0;
+ }
+ return res;
+}
+
+int NdbScanOperation::nextResultImpl(bool fetchAllowed, bool forceSend)
+{
if(m_ordered)
return ((NdbIndexScanOperation*)this)->next_result_ordered(fetchAllowed,
forceSend);
@@ -467,6 +437,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
int retVal = 2;
Uint32 idx = m_current_api_receiver;
Uint32 last = m_api_receivers_count;
+ m_curr_row = 0;
if(DEBUG_NEXT_RESULT)
ndbout_c("nextResult(%d) idx=%d last=%d", fetchAllowed, idx, last);
@@ -477,7 +448,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
for(; idx < last; idx++){
NdbReceiver* tRec = m_api_receivers[idx];
if(tRec->nextResult()){
- tRec->copyout(theReceiver);
+ m_curr_row = tRec->copyout(theReceiver);
retVal = 0;
break;
}
@@ -553,7 +524,7 @@ int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
for(; idx < last; idx++){
NdbReceiver* tRec = m_api_receivers[idx];
if(tRec->nextResult()){
- tRec->copyout(theReceiver);
+ m_curr_row = tRec->copyout(theReceiver);
retVal = 0;
break;
}
@@ -675,11 +646,17 @@ NdbScanOperation::doSend(int ProcessorId)
return 0;
}
-void NdbScanOperation::closeScan(bool forceSend, bool releaseOp)
+void NdbScanOperation::close(bool forceSend, bool releaseOp)
{
+ DBUG_ENTER("NdbScanOperation::close");
+ DBUG_PRINT("enter", ("this=%x tcon=%x con=%x force=%d release=%d",
+ (UintPtr)this,
+ (UintPtr)m_transConnection, (UintPtr)theNdbCon,
+ forceSend, releaseOp));
+
if(m_transConnection){
if(DEBUG_NEXT_RESULT)
- ndbout_c("closeScan() theError.code = %d "
+ ndbout_c("close() theError.code = %d "
"m_api_receivers_count = %d "
"m_conf_receivers_count = %d "
"m_sent_receivers_count = %d",
@@ -706,6 +683,8 @@ void NdbScanOperation::closeScan(bool forceSend, bool releaseOp)
tCon->theScanningOp = 0;
theNdb->closeTransaction(tCon);
+ theNdb->theRemainingStartTransactions--;
+ DBUG_VOID_RETURN;
}
void
@@ -717,17 +696,19 @@ NdbScanOperation::execCLOSE_SCAN_REP(){
void NdbScanOperation::release()
{
if(theNdbCon != 0 || m_transConnection != 0){
- closeScan();
+ close();
}
for(Uint32 i = 0; i<m_allocated_receivers; i++){
m_receivers[i]->release();
}
+
+ NdbOperation::release();
+
if(theSCAN_TABREQ)
{
theNdb->releaseSignal(theSCAN_TABREQ);
theSCAN_TABREQ = 0;
}
- NdbOperation::release();
}
/***************************************************************************
@@ -774,13 +755,14 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
* The number of records sent by each LQH is calculated and the kernel
* is informed of this number by updating the SCAN_TABREQ signal
*/
- Uint32 batch_size, batch_byte_size, first_batch_size;
+ ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
+ Uint32 batch_size = req->first_batch_size; // User specified
+ Uint32 batch_byte_size, first_batch_size;
theReceiver.calculate_batch_size(key_size,
theParallelism,
batch_size,
batch_byte_size,
first_batch_size);
- ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
ScanTabReq::setScanBatch(req->requestInfo, batch_size);
req->batch_byte_size= batch_byte_size;
req->first_batch_size= first_batch_size;
@@ -794,7 +776,9 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
req->requestInfo = reqInfo;
for(Uint32 i = 0; i<theParallelism; i++){
- m_receivers[i]->do_get_value(&theReceiver, batch_size, key_size);
+ m_receivers[i]->do_get_value(&theReceiver, batch_size,
+ key_size,
+ m_read_range_no);
}
return 0;
}
@@ -822,10 +806,6 @@ NdbScanOperation::doSendScan(int aProcessorId)
assert(theSCAN_TABREQ != NULL);
tSignal = theSCAN_TABREQ;
- if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
- setErrorCode(4001);
- return -1;
- }
Uint32 tupKeyLen = theTupKeyLen;
Uint32 len = theTotalNrOfKeyWordInSignal;
@@ -837,7 +817,12 @@ NdbScanOperation::doSendScan(int aProcessorId)
// we created the ATTRINFO signals after the SCAN_TABREQ signal.
ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
req->attrLenKeyLen = (tupKeyLen << 16) | theTotalCurrAI_Len;
-
+ Uint32 tmp = req->requestInfo;
+ ScanTabReq::setDistributionKeyFlag(tmp, theDistrKeyIndicator_);
+ req->distributionKey = theDistributionKey;
+ req->requestInfo = tmp;
+ tSignal->setLength(ScanTabReq::StaticLength + theDistrKeyIndicator_);
+
TransporterFacade *tp = TransporterFacade::instance();
LinearSectionPtr ptr[3];
ptr[0].p = m_prepared_receivers;
@@ -853,8 +838,8 @@ NdbScanOperation::doSendScan(int aProcessorId)
tSignal = theLastKEYINFO;
tSignal->setLength(KeyInfo::HeaderLength + theTotalNrOfKeyWordInSignal);
- assert(theFirstKEYINFO != NULL);
- tSignal = theFirstKEYINFO;
+ assert(theSCAN_TABREQ->next() != NULL);
+ tSignal = theSCAN_TABREQ->next();
NdbApiSignal* last;
do {
@@ -890,6 +875,7 @@ NdbScanOperation::doSendScan(int aProcessorId)
}
theStatus = WaitResponse;
+ m_curr_row = 0;
m_sent_receivers_count = theParallelism;
if(m_ordered)
{
@@ -901,9 +887,9 @@ NdbScanOperation::doSendScan(int aProcessorId)
}//NdbOperation::doSendScan()
/*****************************************************************************
- * NdbOperation* takeOverScanOp(NdbConnection* updateTrans);
+ * NdbOperation* takeOverScanOp(NdbTransaction* updateTrans);
*
- * Parameters: The update transactions NdbConnection pointer.
+ * Parameters: The update transactions NdbTransaction pointer.
* Return Value: A reference to the transferred operation object
* or NULL if no success.
* Remark: Take over the scanning transactions NdbOperation
@@ -913,8 +899,8 @@ NdbScanOperation::doSendScan(int aProcessorId)
*
* 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
+ * to a NdbTransaction on another Ndb-object.
+ * In this case the receiving NdbTransaction-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
@@ -923,16 +909,9 @@ NdbScanOperation::doSendScan(int aProcessorId)
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])){
-
+ NdbRecAttr * tRecAttr = m_curr_row;
+ if(tRecAttr)
+ {
const Uint32 * src = (Uint32*)tRecAttr->aRef();
memcpy(data, src, 4*size);
return 0;
@@ -941,18 +920,12 @@ NdbScanOperation::getKeyFromKEYINFO20(Uint32* data, unsigned size)
}
NdbOperation*
-NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
+NdbScanOperation::takeOverScanOp(OperationType opType, NdbTransaction* 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])){
-
+ NdbRecAttr * tRecAttr = m_curr_row;
+ if(tRecAttr)
+ {
NdbOperation * newOp = pTrans->getNdbOperation(m_currentTable);
if (newOp == NULL){
return NULL;
@@ -981,13 +954,15 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
}
const Uint32 * src = (Uint32*)tRecAttr->aRef();
const Uint32 tScanInfo = src[len] & 0x3FFFF;
- const Uint32 tTakeOverNode = src[len] >> 20;
+ const Uint32 tTakeOverFragment = src[len] >> 20;
{
UintR scanInfo = 0;
TcKeyReq::setTakeOverScanFlag(scanInfo, 1);
- TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode);
+ TcKeyReq::setTakeOverScanFragment(scanInfo, tTakeOverFragment);
TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo);
newOp->theScanInfo = scanInfo;
+ newOp->theDistrKeyIndicator_ = 1;
+ newOp->theDistributionKey = tTakeOverFragment;
}
// Copy the first 8 words of key info from KEYINF20 into TCKEYREQ
@@ -999,7 +974,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
if(i < len){
NdbApiSignal* tSignal = theNdb->getSignal();
- newOp->theFirstKEYINFO = tSignal;
+ newOp->theTCREQ->next(tSignal);
Uint32 left = len - i;
while(tSignal && left > KeyInfo::DataLength){
@@ -1053,7 +1028,7 @@ NdbScanOperation::getBlobHandle(Uint32 anAttrId)
}
NdbIndexScanOperation::NdbIndexScanOperation(Ndb* aNdb)
- : NdbScanOperation(aNdb)
+ : NdbScanOperation(aNdb, NdbOperation::OrderedIndexScan)
{
}
@@ -1127,6 +1102,11 @@ int
NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
int type, const void* aValue, Uint32 len)
{
+ if (!tAttrInfo)
+ {
+ setErrorCodeAbort(4318); // Invalid attribute
+ return -1;
+ }
if (theOperationType == OpenRangeScanRequest &&
(0 <= type && type <= 4) &&
len <= 8000) {
@@ -1134,37 +1114,28 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
Uint32 currLen = theTotalNrOfKeyWordInSignal;
Uint32 remaining = KeyInfo::DataLength - currLen;
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ bool tDistrKey = tAttrInfo->m_distributionKey;
- // normalize char bound
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- Uint32 xfrmData[2000];
- if (cs != NULL && aValue != NULL) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply <= 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
+ len = aValue != NULL ? sizeInBytes : 0;
if (len != sizeInBytes && (len != 0)) {
setErrorCodeAbort(4209);
return -1;
}
+
// insert attribute header
- len = aValue != NULL ? sizeInBytes : 0;
Uint32 tIndexAttrId = tAttrInfo->m_attrId;
Uint32 sizeInWords = (len + 3) / 4;
AttributeHeader ah(tIndexAttrId, sizeInWords);
const Uint32 ahValue = ah.m_value;
- const bool aligned = (UintPtr(aValue) & 3) == 0;
+ const Uint32 align = (UintPtr(aValue) & 7);
+ const bool aligned = (tDistrKey && type == BoundEQ) ?
+ (align == 0) : (align & 3) == 0;
+
const bool nobytes = (len & 0x3) == 0;
const Uint32 totalLen = 2 + sizeInWords;
Uint32 tupKeyLen = theTupKeyLen;
- if(remaining > totalLen && aligned && nobytes){
+ if(remaining > totalLen && aligned && nobytes){
Uint32 * dst = theKEYINFOptr + currLen;
* dst ++ = type;
* dst ++ = ahValue;
@@ -1172,12 +1143,12 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
theTotalNrOfKeyWordInSignal = currLen + totalLen;
} else {
if(!aligned || !nobytes){
- Uint32 tempData[2002];
+ Uint32 tempData[2000];
tempData[0] = type;
tempData[1] = ahValue;
+ tempData[2 + (len >> 2)] = 0;
memcpy(tempData+2, aValue, len);
- while ((len & 0x3) != 0)
- ((char*)&tempData[2])[len++] = 0;
+
insertBOUNDS(tempData, 2+sizeInWords);
} else {
Uint32 buf[2] = { type, ahValue };
@@ -1196,11 +1167,11 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
* 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;
+ if(type == BoundEQ && tDistrKey)
+ {
+ theNoOfTupKeyLeft--;
+ return handle_distribution_key((Uint64*)aValue, sizeInWords);
}
-
return 0;
} else {
setErrorCodeAbort(4228); // XXX wrong code
@@ -1248,15 +1219,32 @@ error:
return -1;
}
-NdbResultSet*
+int
NdbIndexScanOperation::readTuples(LockMode lm,
- Uint32 batch,
+ Uint32 scan_flags,
Uint32 parallel,
- bool order_by,
- bool keyinfo){
- NdbResultSet * rs = NdbScanOperation::readTuples(lm, batch, 0, keyinfo);
- if(rs && order_by){
- m_ordered = 1;
+ Uint32 batch)
+{
+ const bool order_by = scan_flags & SF_OrderBy;
+ const bool order_desc = scan_flags & SF_Descending;
+ const bool read_range_no = scan_flags & SF_ReadRangeNo;
+
+ int res = NdbScanOperation::readTuples(lm, scan_flags, parallel, batch);
+ if(!res && read_range_no)
+ {
+ m_read_range_no = 1;
+ Uint32 word = 0;
+ AttributeHeader::init(&word, AttributeHeader::RANGE_NO, 0);
+ if(insertATTRINFO(word) == -1)
+ res = -1;
+ }
+ if(!res && order_by){
+ m_ordered = true;
+ if (order_desc) {
+ m_descending = true;
+ ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
+ ScanTabReq::setDescendingFlag(req->requestInfo, true);
+ }
Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
m_sort_columns = cnt; // -1 for NDB$NODE
m_current_api_receiver = m_sent_receivers_count;
@@ -1275,7 +1263,10 @@ NdbIndexScanOperation::readTuples(LockMode lm,
#endif
}
}
- return rs;
+ m_this_bound_start = 0;
+ m_first_bound_word = theKEYINFOptr;
+
+ return res;
}
void
@@ -1317,22 +1308,23 @@ NdbIndexScanOperation::compare(Uint32 skip, Uint32 cols,
r1 = (skip ? r1->next() : r1);
r2 = (skip ? r2->next() : r2);
-
+ const int jdir = 1 - 2 * (int)m_descending;
+ assert(jdir == 1 || jdir == -1);
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);
+ return (r1_null ? -1 : 1) * jdir;
}
const NdbColumnImpl & col = NdbColumnImpl::getImpl(* r1->m_column);
- Uint32 size = (r1->theAttrSize * r1->theArraySize + 3) / 4;
+ Uint32 len = r1->theAttrSize * r1->theArraySize;
if(!r1_null){
- const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(col.m_extType);
- int r = (*sqlType.m_cmp)(col.m_cs, d1, d2, size, size);
+ const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getType(col.m_type);
+ int r = (*sqlType.m_cmp)(col.m_cs, d1, len, d2, len, true);
if(r){
assert(r != NdbSqlUtil::CmpUnknown);
- return r;
+ return r * jdir;
}
}
cols--;
@@ -1346,6 +1338,7 @@ int
NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
bool forceSend){
+ m_curr_row = 0;
Uint32 u_idx = 0, u_last = 0;
Uint32 s_idx = m_current_api_receiver; // first sorted
Uint32 s_last = theParallelism; // last sorted
@@ -1419,7 +1412,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
s_idx, s_last);
- Uint32 cols = m_sort_columns;
+ Uint32 cols = m_sort_columns + m_read_range_no;
Uint32 skip = m_keyInfo;
while(u_idx < u_last){
u_last--;
@@ -1456,7 +1449,7 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
tRec = m_api_receivers[s_idx];
if(s_idx < s_last && tRec->nextResult()){
- tRec->copyout(theReceiver);
+ m_curr_row = tRec->copyout(theReceiver);
if(DEBUG_NEXT_RESULT) ndbout_c("return 0");
return 0;
}
@@ -1675,10 +1668,14 @@ NdbIndexScanOperation::reset_bounds(bool forceSend){
theError.code = 0;
reset_receivers(theParallelism, m_ordered);
- theLastKEYINFO = theFirstKEYINFO;
- theKEYINFOptr = ((KeyInfo*)theFirstKEYINFO->getDataPtrSend())->keyData;
+ theLastKEYINFO = theSCAN_TABREQ->next();
+ theKEYINFOptr = ((KeyInfo*)theLastKEYINFO->getDataPtrSend())->keyData;
theTupKeyLen = 0;
theTotalNrOfKeyWordInSignal = 0;
+ theNoOfTupKeyLeft = m_accessTable->m_noOfDistributionKeys;
+ theDistrKeyIndicator_ = 0;
+ m_this_bound_start = 0;
+ m_first_bound_word = theKEYINFOptr;
m_transConnection
->remove_list((NdbOperation*&)m_transConnection->m_firstExecutedScanOp,
this);
@@ -1687,3 +1684,33 @@ NdbIndexScanOperation::reset_bounds(bool forceSend){
}
return res;
}
+
+int
+NdbIndexScanOperation::end_of_bound(Uint32 no)
+{
+ if(no < (1 << 13)) // Only 12-bits no of ranges
+ {
+ Uint32 bound_head = * m_first_bound_word;
+ bound_head |= (theTupKeyLen - m_this_bound_start) << 16 | (no << 4);
+ * m_first_bound_word = bound_head;
+
+ m_first_bound_word = theKEYINFOptr + theTotalNrOfKeyWordInSignal;;
+ m_this_bound_start = theTupKeyLen;
+ return 0;
+ }
+ return -1;
+}
+
+int
+NdbIndexScanOperation::get_range_no()
+{
+ NdbRecAttr* tRecAttr = m_curr_row;
+ if(m_read_range_no && tRecAttr)
+ {
+ if(m_keyInfo)
+ tRecAttr = tRecAttr->next();
+ Uint32 ret = *(Uint32*)tRecAttr->aRef();
+ return ret;
+ }
+ return -1;
+}
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbTransaction.cpp
index 9cd7d6ed42e..e82e02067a6 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbTransaction.cpp
@@ -16,7 +16,7 @@
#include <ndb_global.h>
#include <NdbOut.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include <NdbScanOperation.hpp>
#include <NdbIndexScanOperation.hpp>
@@ -25,7 +25,6 @@
#include "TransporterFacade.hpp"
#include "API.hpp"
#include "NdbBlob.hpp"
-#include <ndb_limits.h>
#include <signaldata/TcKeyConf.hpp>
#include <signaldata/TcIndx.hpp>
@@ -34,13 +33,13 @@
#include <signaldata/TcHbRep.hpp>
/*****************************************************************************
-NdbConnection( Ndb* aNdb );
+NdbTransaction( Ndb* aNdb );
Return Value: None
Parameters: aNdb: Pointers to the Ndb object
Remark: Creates a connection object.
*****************************************************************************/
-NdbConnection::NdbConnection( Ndb* aNdb ) :
+NdbTransaction::NdbTransaction( Ndb* aNdb ) :
theSendStatus(NotInit),
theCallbackFunction(NULL),
theCallbackObject(NULL),
@@ -89,19 +88,19 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
CHECK_SZ(m_db_nodes, NdbNodeBitmask::Size);
CHECK_SZ(m_failed_db_nodes, NdbNodeBitmask::Size);
-}//NdbConnection::NdbConnection()
+}//NdbTransaction::NdbTransaction()
/*****************************************************************************
-~NdbConnection();
+~NdbTransaction();
Remark: Deletes the connection object.
*****************************************************************************/
-NdbConnection::~NdbConnection()
+NdbTransaction::~NdbTransaction()
{
- DBUG_ENTER("NdbConnection::~NdbConnection");
+ DBUG_ENTER("NdbTransaction::~NdbTransaction");
theNdb->theImpl->theNdbObjectIdMap.unmap(theId, this);
DBUG_VOID_RETURN;
-}//NdbConnection::~NdbConnection()
+}//NdbTransaction::~NdbTransaction()
/*****************************************************************************
void init();
@@ -109,7 +108,7 @@ void init();
Remark: Initialise connection object for new transaction.
*****************************************************************************/
void
-NdbConnection::init()
+NdbTransaction::init()
{
theListState = NotInList;
theInUseState = true;
@@ -149,7 +148,7 @@ NdbConnection::init()
//
theBlobFlag = false;
thePendingBlobOps = 0;
-}//NdbConnection::init()
+}//NdbTransaction::init()
/*****************************************************************************
setOperationErrorCode(int error);
@@ -158,9 +157,9 @@ Remark: Sets an error code on the connection object from an
operation object.
*****************************************************************************/
void
-NdbConnection::setOperationErrorCode(int error)
+NdbTransaction::setOperationErrorCode(int error)
{
- DBUG_ENTER("NdbConnection::setOperationErrorCode");
+ DBUG_ENTER("NdbTransaction::setOperationErrorCode");
setErrorCode(error);
DBUG_VOID_RETURN;
}
@@ -172,9 +171,9 @@ Remark: Sets an error code on the connection object from an
operation object.
*****************************************************************************/
void
-NdbConnection::setOperationErrorCodeAbort(int error, int abortOption)
+NdbTransaction::setOperationErrorCodeAbort(int error, int abortOption)
{
- DBUG_ENTER("NdbConnection::setOperationErrorCodeAbort");
+ DBUG_ENTER("NdbTransaction::setOperationErrorCodeAbort");
if (abortOption == -1)
abortOption = m_abortOption;
if (theTransactionIsStarted == false) {
@@ -194,20 +193,20 @@ setErrorCode(int anErrorCode);
Remark: Sets an error indication on the connection object.
*****************************************************************************/
void
-NdbConnection::setErrorCode(int error)
+NdbTransaction::setErrorCode(int error)
{
- DBUG_ENTER("NdbConnection::setErrorCode");
+ DBUG_ENTER("NdbTransaction::setErrorCode");
DBUG_PRINT("enter", ("error: %d, theError.code: %d", error, theError.code));
if (theError.code == 0)
theError.code = error;
DBUG_VOID_RETURN;
-}//NdbConnection::setErrorCode()
+}//NdbTransaction::setErrorCode()
int
-NdbConnection::restart(){
- DBUG_ENTER("NdbConnection::restart");
+NdbTransaction::restart(){
+ DBUG_ENTER("NdbTransaction::restart");
if(theCompletionStatus == CompletedSuccess){
releaseCompletedOperations();
Uint64 tTransid = theNdb->theFirstTransId;
@@ -232,23 +231,8 @@ void handleExecuteCompletion(void);
Remark: Handle time-out on a transaction object.
*****************************************************************************/
void
-NdbConnection::handleExecuteCompletion()
+NdbTransaction::handleExecuteCompletion()
{
-
- if (theCompletionStatus == CompletedFailure) {
- NdbOperation* tOpTemp = theFirstExecOpInList;
- while (tOpTemp != NULL) {
-/*****************************************************************************
- * Ensure that all executing operations report failed for each
- * read attribute when failure occurs.
- * We do not want any operations to report both failure and
- * success on different read attributes.
- ****************************************************************************/
- tOpTemp->handleFailedAI_ElemLen();
- tOpTemp = tOpTemp->next();
- }//while
- theReturnStatus = ReturnFailure;
- }//if
/***************************************************************************
* Move the NdbOperation objects from the list of executing
* operations to list of completed
@@ -265,7 +249,7 @@ NdbConnection::handleExecuteCompletion()
}//if
theSendStatus = InitState;
return;
-}//NdbConnection::handleExecuteCompletion()
+}//NdbTransaction::handleExecuteCompletion()
/*****************************************************************************
int execute(ExecType aTypeOfExec, CommitType aTypeOfCommit, int forceSend);
@@ -276,12 +260,12 @@ Parameters : aTypeOfExec: Type of execute.
Remark: Initialise connection object for new transaction.
*****************************************************************************/
int
-NdbConnection::execute(ExecType aTypeOfExec,
+NdbTransaction::execute(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
NdbError savedError= theError;
- DBUG_ENTER("NdbConnection::execute");
+ DBUG_ENTER("NdbTransaction::execute");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption));
@@ -432,11 +416,11 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
int
-NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
+NdbTransaction::executeNoBlobs(ExecType aTypeOfExec,
AbortOption abortOption,
int forceSend)
{
- DBUG_ENTER("NdbConnection::executeNoBlobs");
+ DBUG_ENTER("NdbTransaction::executeNoBlobs");
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
aTypeOfExec, abortOption));
@@ -445,7 +429,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
// since last execute or since beginning. If this works ok we will continue
// by calling the poll with wait method. This method will return when
// the NDB kernel has completed its task or when 10 seconds have passed.
-// The NdbConnectionCallBack-method will receive the return code of the
+// The NdbTransactionCallBack-method will receive the return code of the
// transaction. The normal methods of reading error codes still apply.
//------------------------------------------------------------------------
Ndb* tNdb = theNdb;
@@ -493,7 +477,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
}
thePendingBlobOps = 0;
DBUG_RETURN(0);
-}//NdbConnection::execute()
+}//NdbTransaction::execute()
/*****************************************************************************
void executeAsynchPrepare(ExecType aTypeOfExec,
@@ -511,12 +495,12 @@ Parameters : aTypeOfExec: Type of execute.
Remark: Prepare a part of a transaction in an asynchronous manner.
*****************************************************************************/
void
-NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
+NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec,
NdbAsynchCallback aCallback,
void* anyObject,
AbortOption abortOption)
{
- DBUG_ENTER("NdbConnection::executeAsynchPrepare");
+ DBUG_ENTER("NdbTransaction::executeAsynchPrepare");
DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: %x, anyObject: %x",
aTypeOfExec, aCallback, anyObject));
@@ -679,14 +663,14 @@ NdbConnection::executeAsynchPrepare( ExecType aTypeOfExec,
NdbNodeBitmask::clear(m_db_nodes);
NdbNodeBitmask::clear(m_failed_db_nodes);
DBUG_VOID_RETURN;
-}//NdbConnection::executeAsynchPrepare()
+}//NdbTransaction::executeAsynchPrepare()
-void NdbConnection::close()
+void NdbTransaction::close()
{
theNdb->closeTransaction(this);
}
-int NdbConnection::refresh(){
+int NdbTransaction::refresh(){
return sendTC_HBREP();
}
@@ -698,7 +682,7 @@ Parameters : None.
Remark: Order NDB to refresh the timeout counter of the transaction.
******************************************************************************/
int
-NdbConnection::sendTC_HBREP() // Send a TC_HBREP signal;
+NdbTransaction::sendTC_HBREP() // Send a TC_HBREP signal;
{
NdbApiSignal* tSignal;
Ndb* tNdb = theNdb;
@@ -733,7 +717,7 @@ NdbConnection::sendTC_HBREP() // Send a TC_HBREP signal;
}
return 0;
-}//NdbConnection::sendTC_HBREP()
+}//NdbTransaction::sendTC_HBREP()
/*****************************************************************************
int doSend();
@@ -745,9 +729,9 @@ Remark: Send all operations belonging to this connection.
object from the prepared transactions array on the Ndb-object.
*****************************************************************************/
int
-NdbConnection::doSend()
+NdbTransaction::doSend()
{
- DBUG_ENTER("NdbConnection::doSend");
+ DBUG_ENTER("NdbTransaction::doSend");
/*
This method assumes that at least one operation have been defined. This
@@ -806,7 +790,7 @@ NdbConnection::doSend()
theTransactionIsStarted = false;
theCommitStatus = Aborted;
DBUG_RETURN(-1);
-}//NdbConnection::doSend()
+}//NdbTransaction::doSend()
/**************************************************************************
int sendROLLBACK();
@@ -816,7 +800,7 @@ Parameters : None.
Remark: Order NDB to rollback the transaction.
**************************************************************************/
int
-NdbConnection::sendROLLBACK() // Send a TCROLLBACKREQ signal;
+NdbTransaction::sendROLLBACK() // Send a TCROLLBACKREQ signal;
{
Ndb* tNdb = theNdb;
if ((theTransactionIsStarted == true) &&
@@ -860,7 +844,7 @@ NdbConnection::sendROLLBACK() // Send a TCROLLBACKREQ signal;
return 0;
;
}//if
-}//NdbConnection::sendROLLBACK()
+}//NdbTransaction::sendROLLBACK()
/***************************************************************************
int sendCOMMIT();
@@ -871,7 +855,7 @@ Parameters : None.
Remark: Order NDB to commit the transaction.
***************************************************************************/
int
-NdbConnection::sendCOMMIT() // Send a TC_COMMITREQ signal;
+NdbTransaction::sendCOMMIT() // Send a TC_COMMITREQ signal;
{
NdbApiSignal tSignal(theNdb->theMyRef);
Uint32 tTransId1, tTransId2;
@@ -893,7 +877,7 @@ NdbConnection::sendCOMMIT() // Send a TC_COMMITREQ signal;
} else {
return -1;
}//if
-}//NdbConnection::sendCOMMIT()
+}//NdbTransaction::sendCOMMIT()
/******************************************************************************
void release();
@@ -901,7 +885,7 @@ void release();
Remark: Release all operations.
******************************************************************************/
void
-NdbConnection::release(){
+NdbTransaction::release(){
releaseOperations();
if ( (theTransactionIsStarted == true) &&
((theCommitStatus != Committed) &&
@@ -920,10 +904,10 @@ NdbConnection::release(){
abort();
}
#endif
-}//NdbConnection::release()
+}//NdbTransaction::release()
void
-NdbConnection::releaseOps(NdbOperation* tOp){
+NdbTransaction::releaseOps(NdbOperation* tOp){
while (tOp != NULL) {
NdbOperation* tmp = tOp;
tOp->release();
@@ -938,7 +922,7 @@ void releaseOperations();
Remark: Release all operations.
******************************************************************************/
void
-NdbConnection::releaseOperations()
+NdbTransaction::releaseOperations()
{
// Release any open scans
releaseScanOperations(m_theFirstScanOperation);
@@ -958,15 +942,15 @@ NdbConnection::releaseOperations()
m_theFirstScanOperation = NULL;
m_theLastScanOperation = NULL;
m_firstExecutedScanOp = NULL;
-}//NdbConnection::releaseOperations()
+}//NdbTransaction::releaseOperations()
void
-NdbConnection::releaseCompletedOperations()
+NdbTransaction::releaseCompletedOperations()
{
releaseOps(theCompletedFirstOp);
theCompletedFirstOp = NULL;
theCompletedLastOp = NULL;
-}//NdbConnection::releaseOperations()
+}//NdbTransaction::releaseOperations()
/******************************************************************************
void releaseScanOperations();
@@ -975,7 +959,7 @@ Remark: Release all cursor operations.
(NdbScanOperation and NdbIndexOperation)
******************************************************************************/
void
-NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp)
+NdbTransaction::releaseScanOperations(NdbIndexScanOperation* cursorOp)
{
while(cursorOp != 0){
NdbIndexScanOperation* next = (NdbIndexScanOperation*)cursorOp->next();
@@ -983,7 +967,7 @@ NdbConnection::releaseScanOperations(NdbIndexScanOperation* cursorOp)
theNdb->releaseScanOperation(cursorOp);
cursorOp = next;
}
-}//NdbConnection::releaseScanOperations()
+}//NdbTransaction::releaseScanOperations()
/*****************************************************************************
void releaseExecutedScanOperation();
@@ -991,9 +975,9 @@ void releaseExecutedScanOperation();
Remark: Release scan op when hupp'ed trans closed (save memory)
******************************************************************************/
void
-NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
+NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
{
- DBUG_ENTER("NdbConnection::releaseExecutedScanOperation");
+ DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation");
DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp))
// here is one reason to make op lists doubly linked
@@ -1014,7 +998,7 @@ NdbConnection::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
}
}
DBUG_VOID_RETURN;
-}//NdbConnection::releaseExecutedScanOperation()
+}//NdbTransaction::releaseExecutedScanOperation()
/*****************************************************************************
NdbOperation* getNdbOperation(const char* aTableName);
@@ -1024,13 +1008,13 @@ Return Value Return a pointer to a NdbOperation object if getNdbOperation
Return NULL : In all other case.
Parameters: aTableName : Name of the database table.
Remark: Get an operation from NdbOperation idlelist and get the
- NdbConnection object
+ NdbTransaction 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* aTableName)
+NdbTransaction::getNdbOperation(const char* aTableName)
{
if (theCommitStatus == Started){
NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
@@ -1045,7 +1029,7 @@ NdbConnection::getNdbOperation(const char* aTableName)
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbOperation()
+}//NdbTransaction::getNdbOperation()
/*****************************************************************************
NdbOperation* getNdbOperation(int aTableId);
@@ -1055,13 +1039,13 @@ Return Value Return a pointer to a NdbOperation object if getNdbOperation
Return NULL: In all other case.
Parameters: tableId : Id of the database table beeing deleted.
Remark: Get an operation from NdbOperation object idlelist and
- get the NdbConnection object who was fetch by
+ get the NdbTransaction object who was fetch by
startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation
object, synchronous.
*****************************************************************************/
NdbOperation*
-NdbConnection::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
+NdbTransaction::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
{
NdbOperation* tOp;
@@ -1105,15 +1089,15 @@ NdbConnection::getNdbOperation(const NdbTableImpl * tab, NdbOperation* aNextOp)
getNdbOp_error1:
setOperationErrorCodeAbort(4000);
return NULL;
-}//NdbConnection::getNdbOperation()
+}//NdbTransaction::getNdbOperation()
-NdbOperation* NdbConnection::getNdbOperation(const NdbDictionary::Table * table)
+NdbOperation* NdbTransaction::getNdbOperation(const NdbDictionary::Table * table)
{
if (table)
return getNdbOperation(& NdbTableImpl::getImpl(*table));
else
return NULL;
-}//NdbConnection::getNdbOperation()
+}//NdbTransaction::getNdbOperation()
// NdbScanOperation
/*****************************************************************************
@@ -1122,12 +1106,12 @@ NdbScanOperation* getNdbScanOperation(const char* aTableName);
Return Value Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
Return NULL : In all other case.
Parameters: aTableName : Name of the database table.
-Remark: Get an operation from NdbScanOperation idlelist and get the NdbConnection object
+Remark: Get an operation from NdbScanOperation idlelist and get the NdbTransaction object
who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbOperation object.synchronous
******************************************************************************/
NdbScanOperation*
-NdbConnection::getNdbScanOperation(const char* aTableName)
+NdbTransaction::getNdbScanOperation(const char* aTableName)
{
if (theCommitStatus == Started){
NdbTableImpl* tab = theNdb->theDictionary->getTable(aTableName);
@@ -1141,78 +1125,106 @@ NdbConnection::getNdbScanOperation(const char* aTableName)
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbTransaction::getNdbScanOperation()
/*****************************************************************************
-NdbScanOperation* getNdbScanOperation(const char* anIndexName, const char* aTableName);
+NdbScanOperation* getNdbIndexScanOperation(const char* anIndexName, const char* aTableName);
-Return Value Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
+Return Value Return a pointer to a NdbIndexScanOperation object if getNdbIndexScanOperation 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 NdbScanOperation idlelist and get the NdbConnection object
+Remark: Get an operation from NdbIndexScanOperation idlelist and get the NdbTransaction object
who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbOperation object.synchronous
+ getOperation will set the theTableId in the NdbIndexScanOperation object.synchronous
******************************************************************************/
NdbIndexScanOperation*
-NdbConnection::getNdbIndexScanOperation(const char* anIndexName,
+NdbTransaction::getNdbIndexScanOperation(const char* anIndexName,
const char* aTableName)
{
NdbIndexImpl* index =
theNdb->theDictionary->getIndex(anIndexName, aTableName);
+ if (index == 0)
+ {
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return 0;
+ }
NdbTableImpl* table = theNdb->theDictionary->getTable(aTableName);
+ if (table == 0)
+ {
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return 0;
+ }
return getNdbIndexScanOperation(index, table);
}
NdbIndexScanOperation*
-NdbConnection::getNdbIndexScanOperation(const NdbIndexImpl* index,
+NdbTransaction::getNdbIndexScanOperation(const NdbIndexImpl* index,
const NdbTableImpl* table)
{
if (theCommitStatus == Started){
const NdbTableImpl * indexTable = index->getIndexTable();
if (indexTable != 0){
- NdbIndexScanOperation* tOp =
- getNdbScanOperation((NdbTableImpl *) indexTable);
+ NdbIndexScanOperation* tOp = getNdbScanOperation(indexTable);
if(tOp)
{
tOp->m_currentTable = table;
- tOp->m_cursor_type = NdbScanOperation::IndexCursor;
}
+ // Mark that this really an NdbIndexScanOperation
+ tOp->m_type = NdbOperation::OrderedIndexScan;
return tOp;
} else {
- setOperationErrorCodeAbort(theNdb->theError.code);
+ setOperationErrorCodeAbort(4271);
return NULL;
}//if
}
setOperationErrorCodeAbort(4114);
return NULL;
-}//NdbConnection::getNdbIndexScanOperation()
+}//NdbTransaction::getNdbIndexScanOperation()
NdbIndexScanOperation*
-NdbConnection::getNdbIndexScanOperation(const NdbDictionary::Index * index,
+NdbTransaction::getNdbIndexScanOperation(const NdbDictionary::Index * index)
+{
+ if (index)
+ {
+ const NdbDictionary::Table *table=
+ theNdb->theDictionary->getTable(index->getTable());
+
+ if (table)
+ return getNdbIndexScanOperation(index, table);
+
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return NULL;
+ }
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}
+
+NdbIndexScanOperation*
+NdbTransaction::getNdbIndexScanOperation(const NdbDictionary::Index * index,
const NdbDictionary::Table * table)
{
if (index && table)
return getNdbIndexScanOperation(& NdbIndexImpl::getImpl(*index),
& NdbTableImpl::getImpl(*table));
- else
- return NULL;
-}//NdbConnection::getNdbIndexScanOperation()
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}//NdbTransaction::getNdbIndexScanOperation()
/*****************************************************************************
NdbScanOperation* getNdbScanOperation(int aTableId);
-Return Value Return a pointer to a NdbOperation object if getNdbOperation was succesful.
+Return Value Return a pointer to a NdbScanOperation object if getNdbScanOperation was succesful.
Return NULL: In all other case.
Parameters: tableId : Id of the database table beeing deleted.
-Remark: Get an operation from NdbScanOperation object idlelist and get the NdbConnection
+Remark: Get an operation from NdbScanOperation object idlelist and get the NdbTransaction
object who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbOperation object, synchronous.
+ getOperation will set the theTableId in the NdbScanOperation object, synchronous.
*****************************************************************************/
NdbIndexScanOperation*
-NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
+NdbTransaction::getNdbScanOperation(const NdbTableImpl * tab)
{
NdbIndexScanOperation* tOp;
@@ -1222,6 +1234,8 @@ NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
if (tOp->init(tab, this) != -1) {
define_scan_op(tOp);
+ // Mark that this NdbIndexScanOperation is used as NdbScanOperation
+ tOp->m_type = NdbOperation::TableScan;
return tOp;
} else {
theNdb->releaseScanOperation(tOp);
@@ -1231,10 +1245,10 @@ NdbConnection::getNdbScanOperation(const NdbTableImpl * tab)
getNdbOp_error1:
setOperationErrorCodeAbort(4000);
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbTransaction::getNdbScanOperation()
void
-NdbConnection::remove_list(NdbOperation*& list, NdbOperation* op){
+NdbTransaction::remove_list(NdbOperation*& list, NdbOperation* op){
NdbOperation* tmp= list;
if(tmp == op)
list = op->next();
@@ -1247,7 +1261,7 @@ NdbConnection::remove_list(NdbOperation*& list, NdbOperation* op){
}
void
-NdbConnection::define_scan_op(NdbIndexScanOperation * tOp){
+NdbTransaction::define_scan_op(NdbIndexScanOperation * tOp){
// Link scan operation into list of cursor operations
if (m_theLastScanOperation == NULL)
m_theFirstScanOperation = m_theLastScanOperation = tOp;
@@ -1259,13 +1273,13 @@ NdbConnection::define_scan_op(NdbIndexScanOperation * tOp){
}
NdbScanOperation*
-NdbConnection::getNdbScanOperation(const NdbDictionary::Table * table)
+NdbTransaction::getNdbScanOperation(const NdbDictionary::Table * table)
{
if (table)
return getNdbScanOperation(& NdbTableImpl::getImpl(*table));
else
return NULL;
-}//NdbConnection::getNdbScanOperation()
+}//NdbTransaction::getNdbScanOperation()
// IndexOperation
@@ -1273,21 +1287,39 @@ NdbConnection::getNdbScanOperation(const NdbDictionary::Table * table)
NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
const char* aTableName);
-Return Value Return a pointer to a NdbOperation object if getNdbScanOperation was succesful.
+Return Value Return a pointer to a NdbOperation object if getNdbIndexOperation was succesful.
Return NULL : In all other case.
Parameters: aTableName : Name of the database table.
-Remark: Get an operation from NdbScanOperation idlelist and get the NdbConnection object
- who was fetch by startTransaction pointing to this operation
- getOperation will set the theTableId in the NdbScanOperation object.synchronous
+Remark: Get an operation from NdbIndexOperation idlelist and get the NdbTransaction object
+ who was fetch by startTransaction pointing to this operation
+ getOperation will set the theTableId in the NdbIndexOperation object.synchronous
******************************************************************************/
NdbIndexOperation*
-NdbConnection::getNdbIndexOperation(const char* anIndexName,
+NdbTransaction::getNdbIndexOperation(const char* anIndexName,
const char* aTableName)
{
if (theCommitStatus == Started) {
NdbTableImpl * table = theNdb->theDictionary->getTable(aTableName);
- NdbIndexImpl * index = theNdb->theDictionary->getIndex(anIndexName,
- aTableName);
+ NdbIndexImpl * index;
+
+ if (table == 0)
+ {
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return NULL;
+ }
+
+ if (table->m_frm.get_data())
+ {
+ // This unique index is defined from SQL level
+ static const char* uniqueSuffix= "$unique";
+ BaseString uniqueIndexName(anIndexName);
+ uniqueIndexName.append(uniqueSuffix);
+ index = theNdb->theDictionary->getIndex(uniqueIndexName.c_str(),
+ aTableName);
+ }
+ else
+ index = theNdb->theDictionary->getIndex(anIndexName,
+ aTableName);
if(table != 0 && index != 0){
return getNdbIndexOperation(index, table);
}
@@ -1297,14 +1329,13 @@ NdbConnection::getNdbIndexOperation(const char* anIndexName,
return NULL;
}
- // table == 0
- setOperationErrorCodeAbort(theNdb->theError.code);
+ setOperationErrorCodeAbort(4243);
return NULL;
}
setOperationErrorCodeAbort(4114);
return 0;
-}//NdbConnection::getNdbIndexOperation()
+}//NdbTransaction::getNdbIndexOperation()
/*****************************************************************************
NdbIndexOperation* getNdbIndexOperation(int anIndexId, int aTableId);
@@ -1312,12 +1343,12 @@ NdbIndexOperation* getNdbIndexOperation(int anIndexId, int aTableId);
Return Value Return a pointer to a NdbIndexOperation object if getNdbIndexOperation was succesful.
Return NULL: In all other case.
Parameters: tableId : Id of the database table beeing deleted.
-Remark: Get an operation from NdbIndexOperation object idlelist and get the NdbConnection
+Remark: Get an operation from NdbIndexOperation object idlelist and get the NdbTransaction
object who was fetch by startTransaction pointing to this operation
getOperation will set the theTableId in the NdbIndexOperation object, synchronous.
*****************************************************************************/
NdbIndexOperation*
-NdbConnection::getNdbIndexOperation(const NdbIndexImpl * anIndex,
+NdbTransaction::getNdbIndexOperation(const NdbIndexImpl * anIndex,
const NdbTableImpl * aTable,
NdbOperation* aNextOp)
{
@@ -1358,18 +1389,37 @@ NdbConnection::getNdbIndexOperation(const NdbIndexImpl * anIndex,
getNdbOp_error1:
setOperationErrorCodeAbort(4000);
return NULL;
-}//NdbConnection::getNdbIndexOperation()
+}//NdbTransaction::getNdbIndexOperation()
NdbIndexOperation*
-NdbConnection::getNdbIndexOperation(const NdbDictionary::Index * index,
+NdbTransaction::getNdbIndexOperation(const NdbDictionary::Index * index)
+{
+ if (index)
+ {
+ const NdbDictionary::Table *table=
+ theNdb->theDictionary->getTable(index->getTable());
+
+ if (table)
+ return getNdbIndexOperation(index, table);
+
+ setOperationErrorCodeAbort(theNdb->theDictionary->getNdbError().code);
+ return NULL;
+ }
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}
+
+NdbIndexOperation*
+NdbTransaction::getNdbIndexOperation(const NdbDictionary::Index * index,
const NdbDictionary::Table * table)
{
if (index && table)
return getNdbIndexOperation(& NdbIndexImpl::getImpl(*index),
& NdbTableImpl::getImpl(*table));
- else
- return NULL;
-}//NdbConnection::getNdbIndexOperation()
+
+ setOperationErrorCodeAbort(4271);
+ return NULL;
+}//NdbTransaction::getNdbIndexOperation()
/*******************************************************************************
@@ -1381,7 +1431,7 @@ Parameters: aSignal: The signal object pointer.
Remark: Sets theRestartGCI in the NDB object.
*******************************************************************************/
int
-NdbConnection::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
+NdbTransaction::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
{
if (theStatus != Connecting) {
return -1;
@@ -1390,7 +1440,7 @@ NdbConnection::receiveDIHNDBTAMPER(NdbApiSignal* aSignal)
theStatus = Connected;
}//if
return 0;
-}//NdbConnection::receiveDIHNDBTAMPER()
+}//NdbTransaction::receiveDIHNDBTAMPER()
/*******************************************************************************
int receiveTCSEIZECONF(NdbApiSignal* aSignal);
@@ -1401,7 +1451,7 @@ Parameters: aSignal: The signal object pointer.
Remark: Sets TC Connect pointer at reception of TCSEIZECONF.
*******************************************************************************/
int
-NdbConnection::receiveTCSEIZECONF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCSEIZECONF(NdbApiSignal* aSignal)
{
if (theStatus != Connecting)
{
@@ -1412,7 +1462,7 @@ NdbConnection::receiveTCSEIZECONF(NdbApiSignal* aSignal)
theStatus = Connected;
}
return 0;
-}//NdbConnection::receiveTCSEIZECONF()
+}//NdbTransaction::receiveTCSEIZECONF()
/*******************************************************************************
int receiveTCSEIZEREF(NdbApiSignal* aSignal);
@@ -1423,18 +1473,22 @@ Parameters: aSignal: The signal object pointer.
Remark: Sets TC Connect pointer.
*******************************************************************************/
int
-NdbConnection::receiveTCSEIZEREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCSEIZEREF(NdbApiSignal* aSignal)
{
+ DBUG_ENTER("NdbTransaction::receiveTCSEIZEREF");
if (theStatus != Connecting)
{
- return -1;
+ DBUG_RETURN(-1);
} else
{
theStatus = ConnectFailure;
theNdb->theError.code = aSignal->readData(2);
- return 0;
+ DBUG_PRINT("info",("error code %d, %s",
+ theNdb->getNdbError().code,
+ theNdb->getNdbError().message));
+ DBUG_RETURN(0);
}
-}//NdbConnection::receiveTCSEIZEREF()
+}//NdbTransaction::receiveTCSEIZEREF()
/*******************************************************************************
int receiveTCRELEASECONF(NdbApiSignal* aSignal);
@@ -1445,7 +1499,7 @@ Parameters: aSignal: The signal object pointer.
Remark: DisConnect TC Connect pointer to NDBAPI.
*******************************************************************************/
int
-NdbConnection::receiveTCRELEASECONF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCRELEASECONF(NdbApiSignal* aSignal)
{
if (theStatus != DisConnecting)
{
@@ -1455,7 +1509,7 @@ NdbConnection::receiveTCRELEASECONF(NdbApiSignal* aSignal)
theStatus = NotConnected;
}
return 0;
-}//NdbConnection::receiveTCRELEASECONF()
+}//NdbTransaction::receiveTCRELEASECONF()
/*******************************************************************************
int receiveTCRELEASEREF(NdbApiSignal* aSignal);
@@ -1466,7 +1520,7 @@ Parameters: aSignal: The signal object pointer.
Remark: DisConnect TC Connect pointer to NDBAPI Failure.
*******************************************************************************/
int
-NdbConnection::receiveTCRELEASEREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCRELEASEREF(NdbApiSignal* aSignal)
{
if (theStatus != DisConnecting) {
return -1;
@@ -1475,7 +1529,7 @@ NdbConnection::receiveTCRELEASEREF(NdbApiSignal* aSignal)
theNdb->theError.code = aSignal->readData(2);
return 0;
}//if
-}//NdbConnection::receiveTCRELEASEREF()
+}//NdbTransaction::receiveTCRELEASEREF()
/******************************************************************************
int receiveTC_COMMITCONF(NdbApiSignal* aSignal);
@@ -1486,11 +1540,12 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
+NdbTransaction::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
{
if(checkState_TransId(&commitConf->transId1)){
theCommitStatus = Committed;
theCompletionStatus = CompletedSuccess;
+ theGlobalCheckpointId = commitConf->gci;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1498,7 +1553,7 @@ NdbConnection::receiveTC_COMMITCONF(const TcCommitConf * commitConf)
#endif
}
return -1;
-}//NdbConnection::receiveTC_COMMITCONF()
+}//NdbTransaction::receiveTC_COMMITCONF()
/******************************************************************************
int receiveTC_COMMITREF(NdbApiSignal* aSignal);
@@ -1509,13 +1564,14 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTC_COMMITREF(NdbApiSignal* aSignal)
{
const TcCommitRef * ref = CAST_CONSTPTR(TcCommitRef, aSignal->getDataPtr());
if(checkState_TransId(&ref->transId1)){
setOperationErrorCodeAbort(ref->errorCode);
theCommitStatus = Aborted;
theCompletionStatus = CompletedFailure;
+ theReturnStatus = ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1524,7 +1580,7 @@ NdbConnection::receiveTC_COMMITREF(NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTC_COMMITREF()
+}//NdbTransaction::receiveTC_COMMITREF()
/******************************************************************************
int receiveTCROLLBACKCONF(NdbApiSignal* aSignal);
@@ -1535,7 +1591,7 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
{
if(checkState_TransId(aSignal->getDataPtr() + 1)){
theCommitStatus = Aborted;
@@ -1548,7 +1604,7 @@ NdbConnection::receiveTCROLLBACKCONF(NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTCROLLBACKCONF()
+}//NdbTransaction::receiveTCROLLBACKCONF()
/*******************************************************************************
int receiveTCROLLBACKREF(NdbApiSignal* aSignal);
@@ -1559,12 +1615,13 @@ Parameters: aSignal: The signal object pointer.
Remark:
*******************************************************************************/
int
-NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
{
if(checkState_TransId(aSignal->getDataPtr() + 1)){
setOperationErrorCodeAbort(aSignal->readData(4));
theCommitStatus = Aborted;
theCompletionStatus = CompletedFailure;
+ theReturnStatus = ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1573,7 +1630,7 @@ NdbConnection::receiveTCROLLBACKREF(NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTCROLLBACKREF()
+}//NdbTransaction::receiveTCROLLBACKREF()
/*****************************************************************************
int receiveTCROLLBACKREP( NdbApiSignal* aSignal)
@@ -1585,7 +1642,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the ROLLBACKREP signal.
*****************************************************************************/
int
-NdbConnection::receiveTCROLLBACKREP( NdbApiSignal* aSignal)
+NdbTransaction::receiveTCROLLBACKREP( NdbApiSignal* aSignal)
{
/****************************************************************************
Check that we are expecting signals from this transaction and that it doesn't
@@ -1604,6 +1661,7 @@ transactions.
/**********************************************************************/
theCompletionStatus = CompletedFailure;
theCommitStatus = Aborted;
+ theReturnStatus = ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1612,7 +1670,7 @@ transactions.
}
return -1;
-}//NdbConnection::receiveTCROLLBACKREP()
+}//NdbTransaction::receiveTCROLLBACKREP()
/*******************************************************************************
int receiveTCKEYCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
@@ -1623,7 +1681,7 @@ Parameters: aSignal: The signal object pointer.
Remark:
*******************************************************************************/
int
-NdbConnection::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength)
+NdbTransaction::receiveTCKEYCONF(const TcKeyConf * keyConf, Uint32 aDataLength)
{
NdbReceiver* tOp;
const Uint32 tTemp = keyConf->confInfo;
@@ -1652,6 +1710,7 @@ from other transactions.
done = 1;
tOp->setErrorCode(4119);
theCompletionStatus = CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
}
}
tNoComp += done;
@@ -1681,6 +1740,7 @@ from other transactions.
/**********************************************************************/
theError.code = 4011;
theCompletionStatus = CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
theCommitStatus = Aborted;
return 0;
}//if
@@ -1695,7 +1755,7 @@ from other transactions.
}
return -1;
-}//NdbConnection::receiveTCKEYCONF()
+}//NdbTransaction::receiveTCKEYCONF()
/*****************************************************************************
int receiveTCKEY_FAILCONF( NdbApiSignal* aSignal)
@@ -1707,7 +1767,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the TCKEY_FAILCONF signal.
*****************************************************************************/
int
-NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
+NdbTransaction::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
{
NdbOperation* tOp;
/*
@@ -1740,6 +1800,7 @@ NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
case NdbOperation::OpenScanRequest:
case NdbOperation::OpenRangeScanRequest:
theCompletionStatus = CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
setOperationErrorCodeAbort(4115);
tOp = NULL;
break;
@@ -1757,7 +1818,7 @@ NdbConnection::receiveTCKEY_FAILCONF(const TcKeyFailConf * failConf)
#endif
}
return -1;
-}//NdbConnection::receiveTCKEY_FAILCONF()
+}//NdbTransaction::receiveTCKEY_FAILCONF()
/*************************************************************************
int receiveTCKEY_FAILREF( NdbApiSignal* aSignal)
@@ -1769,7 +1830,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the TCKEY_FAILREF signal.
**************************************************************************/
int
-NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
+NdbTransaction::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
{
/*
Check that we are expecting signals from this transaction and
@@ -1781,18 +1842,19 @@ NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
We received an indication of that this transaction was aborted due to a
node failure.
*/
- if (theSendStatus == NdbConnection::sendTC_ROLLBACK) {
+ if (theSendStatus == NdbTransaction::sendTC_ROLLBACK) {
/*
We were in the process of sending a rollback anyways. We will
report it as a success.
*/
- theCompletionStatus = NdbConnection::CompletedSuccess;
+ theCompletionStatus = NdbTransaction::CompletedSuccess;
} else {
- theCompletionStatus = NdbConnection::CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
theError.code = 4031;
}//if
theReleaseOnClose = true;
- theCommitStatus = NdbConnection::Aborted;
+ theCommitStatus = NdbTransaction::Aborted;
return 0;
} else {
#ifdef VM_TRACE
@@ -1800,7 +1862,7 @@ NdbConnection::receiveTCKEY_FAILREF(NdbApiSignal* aSignal)
#endif
}
return -1;
-}//NdbConnection::receiveTCKEY_FAILREF()
+}//NdbTransaction::receiveTCKEY_FAILREF()
/******************************************************************************
int receiveTCINDXCONF(NdbApiSignal* aSignal, Uint32 long_short_ind);
@@ -1811,7 +1873,7 @@ Parameters: aSignal: The signal object pointer.
Remark:
******************************************************************************/
int
-NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
+NdbTransaction::receiveTCINDXCONF(const TcIndxConf * indxConf,
Uint32 aDataLength)
{
if(checkState_TransId(&indxConf->transId1)){
@@ -1845,8 +1907,9 @@ NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
// no Commit flag set. This is clearly an anomaly.
/**********************************************************************/
theError.code = 4011;
- theCompletionStatus = NdbConnection::CompletedFailure;
- theCommitStatus = NdbConnection::Aborted;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ theCommitStatus = NdbTransaction::Aborted;
+ theReturnStatus = NdbTransaction::ReturnFailure;
return 0;
}//if
if (tNoComp >= tNoSent) {
@@ -1860,7 +1923,7 @@ NdbConnection::receiveTCINDXCONF(const TcIndxConf * indxConf,
}
return -1;
-}//NdbConnection::receiveTCINDXCONF()
+}//NdbTransaction::receiveTCINDXCONF()
/*****************************************************************************
int receiveTCINDXREF( NdbApiSignal* aSignal)
@@ -1872,7 +1935,7 @@ Parameters: aSignal: the signal object that contains the
Remark: Handles the reception of the TCINDXREF signal.
*****************************************************************************/
int
-NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
+NdbTransaction::receiveTCINDXREF( NdbApiSignal* aSignal)
{
if(checkState_TransId(aSignal->getDataPtr()+1)){
theError.code = aSignal->readData(4); // Override any previous errors
@@ -1884,8 +1947,9 @@ NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
/* and we only need to report completion and return with the */
/* error code to the application. */
/**********************************************************************/
- theCompletionStatus = NdbConnection::CompletedFailure;
- theCommitStatus = NdbConnection::Aborted;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ theCommitStatus = NdbTransaction::Aborted;
+ theReturnStatus = NdbTransaction::ReturnFailure;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1894,7 +1958,7 @@ NdbConnection::receiveTCINDXREF( NdbApiSignal* aSignal)
}
return -1;
-}//NdbConnection::receiveTCINDXREF()
+}//NdbTransaction::receiveTCINDXREF()
/*******************************************************************************
int OpCompletedFailure();
@@ -1905,12 +1969,12 @@ Parameters: aErrorCode: The error code.
Remark: An operation was completed with failure.
*******************************************************************************/
int
-NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure)
+NdbTransaction::OpCompleteFailure(Uint8 abortOption, bool setFailure)
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
if (setFailure)
- theCompletionStatus = NdbConnection::CompletedFailure;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
tNoComp++;
theNoOfOpCompleted = tNoComp;
if (tNoComp == tNoSent) {
@@ -1935,7 +1999,7 @@ NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure)
} else {
return -1; // Continue waiting for more signals
}//if
-}//NdbConnection::OpCompleteFailure()
+}//NdbTransaction::OpCompleteFailure()
/******************************************************************************
int OpCompleteSuccess();
@@ -1945,7 +2009,7 @@ Return Value: Return 0 : OpCompleteSuccess was successful.
Remark: An operation was completed with success.
*******************************************************************************/
int
-NdbConnection::OpCompleteSuccess()
+NdbTransaction::OpCompleteSuccess()
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
@@ -1958,10 +2022,11 @@ NdbConnection::OpCompleteSuccess()
} else {
setOperationErrorCodeAbort(4113); // Too many operations,
// stop waiting for more
- theCompletionStatus = NdbConnection::CompletedFailure;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ theReturnStatus = NdbTransaction::ReturnFailure;
return 0;
}//if
-}//NdbConnection::OpCompleteSuccess()
+}//NdbTransaction::OpCompleteSuccess()
/******************************************************************************
int getGCI();
@@ -1969,13 +2034,13 @@ NdbConnection::OpCompleteSuccess()
Remark: Get global checkpoint identity of the transaction
*******************************************************************************/
int
-NdbConnection::getGCI()
+NdbTransaction::getGCI()
{
- if (theCommitStatus == NdbConnection::Committed) {
+ if (theCommitStatus == NdbTransaction::Committed) {
return theGlobalCheckpointId;
}//if
return 0;
-}//NdbConnection::getGCI()
+}//NdbTransaction::getGCI()
/*******************************************************************************
Uint64 getTransactionId(void);
@@ -1983,31 +2048,31 @@ Uint64 getTransactionId(void);
Remark: Get the transaction identity.
*******************************************************************************/
Uint64
-NdbConnection::getTransactionId()
+NdbTransaction::getTransactionId()
{
return theTransactionId;
-}//NdbConnection::getTransactionId()
+}//NdbTransaction::getTransactionId()
-NdbConnection::CommitStatusType
-NdbConnection::commitStatus()
+NdbTransaction::CommitStatusType
+NdbTransaction::commitStatus()
{
return theCommitStatus;
-}//NdbConnection::commitStatus()
+}//NdbTransaction::commitStatus()
int
-NdbConnection::getNdbErrorLine()
+NdbTransaction::getNdbErrorLine()
{
return theErrorLine;
}
NdbOperation*
-NdbConnection::getNdbErrorOperation()
+NdbTransaction::getNdbErrorOperation()
{
return theErrorOperation;
-}//NdbConnection::getNdbErrorOperation()
+}//NdbTransaction::getNdbErrorOperation()
const NdbOperation *
-NdbConnection::getNextCompletedOperation(const NdbOperation * current) const {
+NdbTransaction::getNextCompletedOperation(const NdbOperation * current) const {
if(current == 0)
return theCompletedFirstOp;
return current->theNext;
@@ -2016,7 +2081,7 @@ NdbConnection::getNextCompletedOperation(const NdbOperation * current) const {
#ifdef VM_TRACE
#define CASE(x) case x: ndbout << " " << #x; break
void
-NdbConnection::printState()
+NdbTransaction::printState()
{
ndbout << "con=" << hex << this << dec;
ndbout << " node=" << getConnectedNodeId();
@@ -2069,7 +2134,7 @@ NdbConnection::printState()
#endif
int
-NdbConnection::report_node_failure(Uint32 id){
+NdbTransaction::report_node_failure(Uint32 id){
NdbNodeBitmask::set(m_failed_db_nodes, id);
if(!NdbNodeBitmask::get(m_db_nodes, id))
{
@@ -2088,22 +2153,28 @@ NdbConnection::report_node_failure(Uint32 id){
const Uint32 len = TcKeyConf::SimpleReadBit | id;
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
+ Uint32 count = 0;
while(tmp != 0)
{
if(tmp->theReceiver.m_expected_result_length == len &&
tmp->theReceiver.m_received_result_length == 0)
{
- tNoComp++;
+ count++;
tmp->theError.code = 4119;
}
tmp = tmp->next();
}
+ tNoComp += count;
theNoOfOpCompleted = tNoComp;
- if(tNoComp == tNoSent)
+ if(count)
{
- theError.code = 4119;
- theCompletionStatus = NdbConnection::CompletedFailure;
- return 1;
+ theReturnStatus = NdbTransaction::ReturnFailure;
+ if(tNoComp == tNoSent)
+ {
+ theError.code = 4119;
+ theCompletionStatus = NdbTransaction::CompletedFailure;
+ return 1;
+ }
}
return 0;
}
diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbTransactionScan.cpp
index b0c546c512a..4c507f6ab8c 100644
--- a/ndb/src/ndbapi/NdbConnectionScan.cpp
+++ b/ndb/src/ndbapi/NdbTransactionScan.cpp
@@ -15,22 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/*****************************************************************************
- * Name: NdbConnectionScan.cpp
- * Include:
- * Link:
- * Author: UABRONM MikaelRonström UAB/M/MT
- * QABJKAM Jonas Kamf UAB/M/MT
- * Date: 2000-06-12
- * Version: 0.1
- * Description: Interface between Application and NDB
- * Documentation:
- * Adjust: 2000-06-12 UABRONM First version.
- ****************************************************************************/
#include <ndb_global.h>
#include <Ndb.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include <NdbScanOperation.hpp>
#include "NdbApiSignal.hpp"
@@ -52,7 +40,7 @@
*
****************************************************************************/
int
-NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
+NdbTransaction::receiveSCAN_TABREF(NdbApiSignal* aSignal){
const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr());
if(checkState_TransId(&ref->transId1)){
@@ -93,7 +81,7 @@ NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
*
*****************************************************************************/
int
-NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
+NdbTransaction::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
const Uint32 * ops, Uint32 len)
{
const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, aSignal->getDataPtr());
diff --git a/ndb/src/ndbapi/Ndberr.cpp b/ndb/src/ndbapi/Ndberr.cpp
index a8b968da03f..ad0b4eafcb4 100644
--- a/ndb/src/ndbapi/Ndberr.cpp
+++ b/ndb/src/ndbapi/Ndberr.cpp
@@ -19,10 +19,9 @@
#include "NdbImpl.hpp"
#include "NdbDictionaryImpl.hpp"
#include <NdbOperation.hpp>
-#include <NdbConnection.hpp>
+#include <NdbTransaction.hpp>
#include <NdbBlob.hpp>
-
static void
update(const NdbError & _err){
NdbError & error = (NdbError &) _err;
@@ -55,7 +54,7 @@ NdbDictionaryImpl::getNdbError() const {
const
NdbError &
-NdbConnection::getNdbError() const {
+NdbTransaction::getNdbError() const {
update(theError);
return theError;
}
diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp
index f1433122ade..6aaf44d0168 100644
--- a/ndb/src/ndbapi/Ndbif.cpp
+++ b/ndb/src/ndbapi/Ndbif.cpp
@@ -19,12 +19,12 @@
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-#include "NdbOperation.hpp"
-#include "NdbIndexOperation.hpp"
-#include "NdbScanOperation.hpp"
-#include "NdbConnection.hpp"
-#include "NdbRecAttr.hpp"
-#include "NdbReceiver.hpp"
+#include <NdbTransaction.hpp>
+#include <NdbOperation.hpp>
+#include <NdbIndexOperation.hpp>
+#include <NdbScanOperation.hpp>
+#include <NdbRecAttr.hpp>
+#include <NdbReceiver.hpp>
#include "API.hpp"
#include <signaldata/TcCommit.hpp>
@@ -107,15 +107,13 @@ Ndb::init(int aMaxNoOfTransactions)
goto error_handler;
}
- tMaxNoOfTransactions = aMaxNoOfTransactions * 3;
- if (tMaxNoOfTransactions > 1024) {
- tMaxNoOfTransactions = 1024;
- }//if
+
+ tMaxNoOfTransactions = aMaxNoOfTransactions;
theMaxNoOfTransactions = tMaxNoOfTransactions;
-
- thePreparedTransactionsArray = new NdbConnection* [tMaxNoOfTransactions];
- theSentTransactionsArray = new NdbConnection* [tMaxNoOfTransactions];
- theCompletedTransactionsArray = new NdbConnection* [tMaxNoOfTransactions];
+ theRemainingStartTransactions= tMaxNoOfTransactions;
+ thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
+ theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
+ theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
if ((thePreparedTransactionsArray == NULL) ||
(theSentTransactionsArray == NULL) ||
@@ -263,11 +261,11 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
{
Uint32 tNoSentTransactions = theNoOfSentTransactions;
for (int i = tNoSentTransactions - 1; i >= 0; i--) {
- NdbConnection* localCon = theSentTransactionsArray[i];
+ NdbTransaction* localCon = theSentTransactionsArray[i];
if (localCon->getConnectedNodeId() == aNodeId) {
- const NdbConnection::SendStatusType sendStatus = localCon->theSendStatus;
- if (sendStatus == NdbConnection::sendTC_OP ||
- sendStatus == NdbConnection::sendTC_COMMIT) {
+ const NdbTransaction::SendStatusType sendStatus = localCon->theSendStatus;
+ if (sendStatus == NdbTransaction::sendTC_OP ||
+ sendStatus == NdbTransaction::sendTC_COMMIT) {
/*
A transaction was interrupted in the prepare phase by a node
failure. Since the transaction was not found in the phase
@@ -275,13 +273,13 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
we report a normal node failure abort.
*/
localCon->setOperationErrorCodeAbort(4010);
- localCon->theCompletionStatus = NdbConnection::CompletedFailure;
- } else if (sendStatus == NdbConnection::sendTC_ROLLBACK) {
+ localCon->theCompletionStatus = NdbTransaction::CompletedFailure;
+ } else if (sendStatus == NdbTransaction::sendTC_ROLLBACK) {
/*
We aimed for abort and abort we got even if it was by a node
failure. We will thus report it as a success.
*/
- localCon->theCompletionStatus = NdbConnection::CompletedSuccess;
+ localCon->theCompletionStatus = NdbTransaction::CompletedSuccess;
} else {
#ifdef VM_TRACE
printState("abortTransactionsAfterNodeFailure %x", this);
@@ -293,7 +291,8 @@ Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
intact since the node was failing and they were aborted. Thus we
set commit state to Aborted and set state to release on close.
*/
- localCon->theCommitStatus = NdbConnection::Aborted;
+ localCon->theReturnStatus = NdbTransaction::ReturnFailure;
+ localCon->theCommitStatus = NdbTransaction::Aborted;
localCon->theReleaseOnClose = true;
completedTransaction(localCon);
}
@@ -316,7 +315,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
{
NdbOperation* tOp;
NdbIndexOperation* tIndexOp;
- NdbConnection* tCon;
+ NdbTransaction* tCon;
int tReturnCode = -1;
const Uint32* tDataPtr = aSignal->getDataPtr();
const Uint32 tWaitState = theImpl->theWaiter.m_state;
@@ -346,14 +345,14 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_OP)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
if (tReturnCode != -1) {
completedTransaction(tCon);
}//if
if(TcKeyConf::getMarkerFlag(keyConf->confInfo)){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
keyConf->transId1,
keyConf->transId2,
aTCRef);
@@ -378,24 +377,24 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength,
tLen - TransIdAI::HeaderLength);
}
+
+ if(com == 0)
+ return;
- 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);
- theImpl->theWaiter.m_state = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
- (Uint32) NO_WAIT : tWaitState);
- break;
- default:
- goto InvalidSignal;
+ switch(tRec->getType()){
+ case NdbReceiver::NDB_OPERATION:
+ case NdbReceiver::NDB_INDEX_OPERATION:
+ if(tCon->OpCompleteSuccess() != -1){
+ completedTransaction(tCon);
}
+ return;
+ case NdbReceiver::NDB_SCANRECEIVER:
+ tCon->theScanningOp->receiver_delivered(tRec);
+ theImpl->theWaiter.m_state = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
+ (Uint32) NO_WAIT : tWaitState);
+ break;
+ default:
+ goto InvalidSignal;
}
break;
} else {
@@ -417,8 +416,8 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber(false) == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
+ (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -432,7 +431,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
#endif
}
if(tFirstData & 1){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
failConf->transId1,
failConf->transId2,
aTCRef);
@@ -447,8 +446,8 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber(false) == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if ((tCon->theSendStatus == NdbConnection::sendTC_OP) ||
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
+ (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -473,7 +472,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tOp->checkMagicNumber() == 0) {
tCon = tOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
+ if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
tReturnCode = tOp->receiveTCKEYREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -496,14 +495,14 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTC_COMMITCONF(commitConf);
if (tReturnCode != -1) {
completedTransaction(tCon);
}//if
if(tFirstData & 1){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
commitConf->transId1,
commitConf->transId2,
aTCRef);
@@ -521,7 +520,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_COMMIT)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -536,7 +535,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCROLLBACKCONF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -551,7 +550,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_ROLLBACK)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -662,29 +661,11 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
case GSN_CREATE_INDX_REF:
case GSN_DROP_INDX_CONF:
case GSN_DROP_INDX_REF:
- case GSN_CREATE_EVNT_CONF:
- case GSN_CREATE_EVNT_REF:
- case GSN_DROP_EVNT_CONF:
- case GSN_DROP_EVNT_REF:
case GSN_LIST_TABLES_CONF:
NdbDictInterface::execSignal(&theDictionary->m_receiver,
aSignal, ptr);
break;
- case GSN_SUB_META_DATA:
- case GSN_SUB_REMOVE_CONF:
- case GSN_SUB_REMOVE_REF:
- break; // ignore these signals
- case GSN_SUB_GCP_COMPLETE_REP:
- case GSN_SUB_START_CONF:
- case GSN_SUB_START_REF:
- case GSN_SUB_TABLE_DATA:
- case GSN_SUB_STOP_CONF:
- case GSN_SUB_STOP_REF:
- NdbDictInterface::execSignal(&theDictionary->m_receiver,
- aSignal, ptr);
- break;
-
case GSN_DIHNDBTAMPER:
{
tFirstDataPtr = int2void(tFirstData);
@@ -788,7 +769,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
const BlockReference aTCRef = aSignal->theSendersBlockRef;
tCon = void2con(tFirstDataPtr);
if ((tCon->checkMagicNumber() == 0) &&
- (tCon->theSendStatus == NdbConnection::sendTC_OP)) {
+ (tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
tReturnCode = tCon->receiveTCINDXCONF(indxConf, tLen);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -796,7 +777,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
}//if
if(TcIndxConf::getMarkerFlag(indxConf->confInfo)){
- NdbConnection::sendTC_COMMIT_ACK(theCommitAckSignal,
+ NdbTransaction::sendTC_COMMIT_ACK(theCommitAckSignal,
indxConf->transId1,
indxConf->transId2,
aTCRef);
@@ -811,7 +792,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
if (tIndexOp->checkMagicNumber() == 0) {
tCon = tIndexOp->theNdbCon;
if (tCon != NULL) {
- if (tCon->theSendStatus == NdbConnection::sendTC_OP) {
+ if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
if (tReturnCode != -1) {
completedTransaction(tCon);
@@ -852,7 +833,7 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
/*****************************************************************************
-void completedTransaction(NdbConnection* aCon);
+void completedTransaction(NdbTransaction* aCon);
Remark: One transaction has been completed.
Remove it from send array and put it into the completed
@@ -860,14 +841,14 @@ Remark: One transaction has been completed.
up a poller.
******************************************************************************/
void
-Ndb::completedTransaction(NdbConnection* aCon)
+Ndb::completedTransaction(NdbTransaction* aCon)
{
Uint32 tTransArrayIndex = aCon->theTransArrayIndex;
Uint32 tNoSentTransactions = theNoOfSentTransactions;
Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
- if ((tNoSentTransactions > 0) && (aCon->theListState == NdbConnection::InSendList) &&
+ if ((tNoSentTransactions > 0) && (aCon->theListState == NdbTransaction::InSendList) &&
(tTransArrayIndex < tNoSentTransactions)) {
- NdbConnection* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
+ NdbTransaction* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
theCompletedTransactionsArray[tNoCompletedTransactions] = aCon;
aCon->theTransArrayIndex = tNoCompletedTransactions;
@@ -879,7 +860,7 @@ Ndb::completedTransaction(NdbConnection* aCon)
theNoOfCompletedTransactions = tNoCompletedTransactions + 1;
theNoOfSentTransactions = tNoSentTransactions - 1;
- aCon->theListState = NdbConnection::InCompletedList;
+ aCon->theListState = NdbTransaction::InCompletedList;
aCon->handleExecuteCompletion();
if ((theMinNoOfEventsToWakeUp != 0) &&
(theNoOfCompletedTransactions >= theMinNoOfEventsToWakeUp)) {
@@ -900,12 +881,12 @@ Ndb::completedTransaction(NdbConnection* aCon)
}//Ndb::completedTransaction()
/*****************************************************************************
-void reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans);
+void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans);
Remark: Call the callback methods of the completed transactions.
******************************************************************************/
void
-Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
+Ndb::reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans)
{
Uint32 i;
if (aNoOfCompletedTrans > 0) {
@@ -914,7 +895,7 @@ Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
NdbAsynchCallback aCallback = aCopyArray[i]->theCallbackFunction;
int tResult = 0;
if (aCallback != NULL) {
- if (aCopyArray[i]->theReturnStatus == NdbConnection::ReturnFailure) {
+ if (aCopyArray[i]->theReturnStatus == NdbTransaction::ReturnFailure) {
tResult = -1;
}//if
(*aCallback)(tResult, aCopyArray[i], anyObject);
@@ -924,13 +905,13 @@ Ndb::reportCallback(NdbConnection** aCopyArray, Uint32 aNoOfCompletedTrans)
}//Ndb::reportCallback()
/*****************************************************************************
-Uint32 pollCompleted(NdbConnection** aCopyArray);
+Uint32 pollCompleted(NdbTransaction** aCopyArray);
Remark: Transfer the data from the completed transaction to a local array.
This support is used by a number of the poll-methods.
******************************************************************************/
Uint32
-Ndb::pollCompleted(NdbConnection** aCopyArray)
+Ndb::pollCompleted(NdbTransaction** aCopyArray)
{
check_send_timeout();
Uint32 i;
@@ -938,13 +919,13 @@ Ndb::pollCompleted(NdbConnection** aCopyArray)
if (tNoCompletedTransactions > 0) {
for (i = 0; i < tNoCompletedTransactions; i++) {
aCopyArray[i] = theCompletedTransactionsArray[i];
- if (aCopyArray[i]->theListState != NdbConnection::InCompletedList) {
+ if (aCopyArray[i]->theListState != NdbTransaction::InCompletedList) {
ndbout << "pollCompleted error ";
ndbout << (int) aCopyArray[i]->theListState << endl;
abort();
}//if
theCompletedTransactionsArray[i] = NULL;
- aCopyArray[i]->theListState = NdbConnection::NotInList;
+ aCopyArray[i]->theListState = NdbTransaction::NotInList;
}//for
}//if
theNoOfCompletedTransactions = 0;
@@ -960,7 +941,7 @@ Ndb::check_send_timeout()
the_last_check_time = current_time;
Uint32 no_of_sent = theNoOfSentTransactions;
for (Uint32 i = 0; i < no_of_sent; i++) {
- NdbConnection* a_con = theSentTransactionsArray[i];
+ NdbTransaction* a_con = theSentTransactionsArray[i];
if ((current_time - a_con->theStartTransTime) > timeout)
{
#ifdef VM_TRACE
@@ -972,8 +953,8 @@ Ndb::check_send_timeout()
#endif
a_con->theReleaseOnClose = true;
a_con->setOperationErrorCodeAbort(4012);
- a_con->theCommitStatus = NdbConnection::NeedAbort;
- a_con->theCompletionStatus = NdbConnection::CompletedFailure;
+ a_con->theCommitStatus = NdbTransaction::NeedAbort;
+ a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
a_con->handleExecuteCompletion();
remove_sent_list(i);
insert_completed_list(a_con);
@@ -989,7 +970,7 @@ Ndb::remove_sent_list(Uint32 list_index)
{
Uint32 last_index = theNoOfSentTransactions - 1;
if (list_index < last_index) {
- NdbConnection* t_con = theSentTransactionsArray[last_index];
+ NdbTransaction* t_con = theSentTransactionsArray[last_index];
theSentTransactionsArray[list_index] = t_con;
}//if
theNoOfSentTransactions = last_index;
@@ -997,23 +978,23 @@ Ndb::remove_sent_list(Uint32 list_index)
}
Uint32
-Ndb::insert_completed_list(NdbConnection* a_con)
+Ndb::insert_completed_list(NdbTransaction* a_con)
{
Uint32 no_of_comp = theNoOfCompletedTransactions;
theCompletedTransactionsArray[no_of_comp] = a_con;
theNoOfCompletedTransactions = no_of_comp + 1;
- a_con->theListState = NdbConnection::InCompletedList;
+ a_con->theListState = NdbTransaction::InCompletedList;
a_con->theTransArrayIndex = no_of_comp;
return no_of_comp;
}
Uint32
-Ndb::insert_sent_list(NdbConnection* a_con)
+Ndb::insert_sent_list(NdbTransaction* a_con)
{
Uint32 no_of_sent = theNoOfSentTransactions;
theSentTransactionsArray[no_of_sent] = a_con;
theNoOfSentTransactions = no_of_sent + 1;
- a_con->theListState = NdbConnection::InSendList;
+ a_con->theListState = NdbTransaction::InSendList;
a_con->theTransArrayIndex = no_of_sent;
return no_of_sent;
}
@@ -1045,16 +1026,16 @@ Ndb::sendPrepTrans(int forceSend)
TransporterFacade* tp = TransporterFacade::instance();
Uint32 no_of_prep_trans = theNoOfPreparedTransactions;
for (i = 0; i < no_of_prep_trans; i++) {
- NdbConnection * a_con = thePreparedTransactionsArray[i];
+ NdbTransaction * a_con = thePreparedTransactionsArray[i];
thePreparedTransactionsArray[i] = NULL;
Uint32 node_id = a_con->getConnectedNodeId();
if ((tp->getNodeSequence(node_id) == a_con->theNodeSequence) &&
tp->get_node_alive(node_id) ||
(tp->get_node_stopping(node_id) &&
- ((a_con->theSendStatus == NdbConnection::sendABORT) ||
- (a_con->theSendStatus == NdbConnection::sendABORTfail) ||
- (a_con->theSendStatus == NdbConnection::sendCOMMITstate) ||
- (a_con->theSendStatus == NdbConnection::sendCompleted)))) {
+ ((a_con->theSendStatus == NdbTransaction::sendABORT) ||
+ (a_con->theSendStatus == NdbTransaction::sendABORTfail) ||
+ (a_con->theSendStatus == NdbTransaction::sendCOMMITstate) ||
+ (a_con->theSendStatus == NdbTransaction::sendCompleted)))) {
/*
We will send if
1) Node is alive and sequences are correct OR
@@ -1086,13 +1067,13 @@ Ndb::sendPrepTrans(int forceSend)
again and will thus set the state to Aborted to avoid a more or
less eternal loop of tries.
*/
- if (a_con->theSendStatus == NdbConnection::sendOperations) {
+ if (a_con->theSendStatus == NdbTransaction::sendOperations) {
a_con->setOperationErrorCodeAbort(4021);
- a_con->theCommitStatus = NdbConnection::NeedAbort;
+ a_con->theCommitStatus = NdbTransaction::NeedAbort;
TRACE_DEBUG("Send buffer full and sendOperations");
} else {
a_con->setOperationErrorCodeAbort(4026);
- a_con->theCommitStatus = NdbConnection::Aborted;
+ a_con->theCommitStatus = NdbTransaction::Aborted;
TRACE_DEBUG("Send buffer full, set state to Aborted");
}//if
}//if
@@ -1109,7 +1090,7 @@ Ndb::sendPrepTrans(int forceSend)
*/
TRACE_DEBUG("Abort a transaction when stopping a node");
a_con->setOperationErrorCodeAbort(4023);
- a_con->theCommitStatus = NdbConnection::NeedAbort;
+ a_con->theCommitStatus = NdbTransaction::NeedAbort;
} else {
/*
The node is hard dead and we cannot continue. We will also release
@@ -1119,10 +1100,11 @@ Ndb::sendPrepTrans(int forceSend)
a_con->setOperationErrorCodeAbort(4025);
a_con->theReleaseOnClose = true;
a_con->theTransactionIsStarted = false;
- a_con->theCommitStatus = NdbConnection::Aborted;
+ a_con->theCommitStatus = NdbTransaction::Aborted;
}//if
}//if
- a_con->theCompletionStatus = NdbConnection::CompletedFailure;
+ a_con->theReturnStatus = NdbTransaction::ReturnFailure;
+ a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
a_con->handleExecuteCompletion();
insert_completed_list(a_con);
}//for
@@ -1196,7 +1178,7 @@ Remark: First send all prepared operations and then check if there are any
int
Ndb::sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup, int forceSend)
{
- NdbConnection* tConArray[1024];
+ NdbTransaction* tConArray[1024];
Uint32 tNoCompletedTransactions;
//theCurrentConnectCounter = 0;
@@ -1229,7 +1211,7 @@ Remark: Check if there are any transactions already completed. Wait for not
int
Ndb::pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup)
{
- NdbConnection* tConArray[1024];
+ NdbTransaction* tConArray[1024];
Uint32 tNoCompletedTransactions;
//theCurrentConnectCounter = 0;
@@ -1336,7 +1318,7 @@ Ndb::sendRecSignal(Uint16 node_id,
}//Ndb::sendRecSignal()
void
-NdbConnection::sendTC_COMMIT_ACK(NdbApiSignal * aSignal,
+NdbTransaction::sendTC_COMMIT_ACK(NdbApiSignal * aSignal,
Uint32 transId1, Uint32 transId2,
Uint32 aTCRef){
#ifdef MARKER_TRACE
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index 59a6a825be4..40cac675b21 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -19,12 +19,12 @@
#include "NdbApiSignal.hpp"
#include "NdbImpl.hpp"
-#include "NdbOperation.hpp"
-#include "NdbConnection.hpp"
-#include "NdbRecAttr.hpp"
-#include "IPCConfig.hpp"
+#include <NdbOperation.hpp>
+#include <NdbTransaction.hpp>
+#include <NdbRecAttr.hpp>
+#include <IPCConfig.hpp>
#include "TransporterFacade.hpp"
-#include "ConfigRetriever.hpp"
+#include <ConfigRetriever.hpp>
#include <ndb_limits.h>
#include <NdbOut.hpp>
#include <NdbSleep.h>
@@ -34,52 +34,12 @@
#include "NdbUtil.hpp"
#include <NdbBlob.hpp>
-class NdbGlobalEventBufferHandle;
-NdbGlobalEventBufferHandle *NdbGlobalEventBuffer_init(int);
-void NdbGlobalEventBuffer_drop(NdbGlobalEventBufferHandle *);
-
-/**
- * Static object for NDB
- */
-
-// only needed for backwards compatability, before ndb_cluster_connection
-static char *ndbConnectString = 0;
-static int theNoOfNdbObjects = 0;
-static Ndb_cluster_connection *global_ndb_cluster_connection= 0;
-
-
-/***************************************************************************
-Ndb(const char* aDataBase);
-
-Parameters: aDataBase : Name of the database.
-Remark: Connect to the database.
-***************************************************************************/
-Ndb::Ndb( const char* aDataBase , const char* aSchema)
- : theImpl(NULL)
-{
- DBUG_ENTER("Ndb::Ndb()");
- DBUG_PRINT("enter",("(old)Ndb::Ndb this=0x%x", this));
- if (theNoOfNdbObjects < 0)
- abort(); // old and new Ndb constructor used mixed
- theNoOfNdbObjects++;
- if (global_ndb_cluster_connection == 0) {
- global_ndb_cluster_connection= new Ndb_cluster_connection(ndbConnectString);
- global_ndb_cluster_connection->connect(12,5,1);
- }
- setup(global_ndb_cluster_connection, aDataBase, aSchema);
- DBUG_VOID_RETURN;
-}
-
Ndb::Ndb( Ndb_cluster_connection *ndb_cluster_connection,
const char* aDataBase , const char* aSchema)
: theImpl(NULL)
{
DBUG_ENTER("Ndb::Ndb()");
DBUG_PRINT("enter",("Ndb::Ndb this=0x%x", this));
- if (global_ndb_cluster_connection != 0 &&
- global_ndb_cluster_connection != ndb_cluster_connection)
- abort(); // old and new Ndb constructor used mixed
- theNoOfNdbObjects= -1;
setup(ndb_cluster_connection, aDataBase, aSchema);
DBUG_VOID_RETURN;
}
@@ -99,10 +59,9 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
theNoOfPreparedTransactions= 0;
theNoOfSentTransactions= 0;
theNoOfCompletedTransactions= 0;
- theNoOfAllocatedTransactions= 0;
+ theRemainingStartTransactions= 0;
theMaxNoOfTransactions= 0;
theMinNoOfEventsToWakeUp= 0;
- prefixEnd= NULL;
theTransactionList= NULL;
theConnectionArray= NULL;
the_last_check_time= 0;
@@ -133,21 +92,10 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
for (i = 0; i < MAX_NDB_NODES ; i++) {
theConnectionArray[i] = NULL;
}//forg
- for (i = 0; i < 2048 ; i++) {
- theFirstTupleId[i] = 0;
- theLastTupleId[i] = 0;
- }//for
-
- BaseString::snprintf(theDataBase, sizeof(theDataBase), "%s",
- aDataBase ? aDataBase : "");
- BaseString::snprintf(theDataBaseSchema, sizeof(theDataBaseSchema), "%s",
- aSchema ? aSchema : "");
- int len = BaseString::snprintf(prefixName, sizeof(prefixName), "%s%c%s%c",
- theDataBase, table_name_separator,
- theDataBaseSchema, table_name_separator);
- prefixEnd = prefixName + (len < (int) sizeof(prefixName) ? len :
- sizeof(prefixName) - 1);
+ theImpl->m_dbname.assign(aDataBase);
+ theImpl->m_schemaname.assign(aSchema);
+ theImpl->update_prefix();
theImpl->theWaiter.m_mutex = TransporterFacade::instance()->theMutexPtr;
@@ -155,30 +103,10 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
if (theInitState == NotConstructed)
theInitState = NotInitialised;
- {
- NdbGlobalEventBufferHandle *h=
- NdbGlobalEventBuffer_init(NDB_MAX_ACTIVE_EVENTS);
- if (h == NULL) {
- ndbout_c("Failed NdbGlobalEventBuffer_init(%d)",NDB_MAX_ACTIVE_EVENTS);
- exit(-1);
- }
- theGlobalEventBufferHandle = h;
- }
-
DBUG_VOID_RETURN;
}
-void Ndb::setConnectString(const char * connectString)
-{
- if (ndbConnectString != 0) {
- free(ndbConnectString);
- ndbConnectString = 0;
- }
- if (connectString)
- ndbConnectString = strdup(connectString);
-}
-
/*****************************************************************************
* ~Ndb();
*
@@ -190,8 +118,6 @@ Ndb::~Ndb()
DBUG_PRINT("enter",("Ndb::~Ndb this=0x%x",this));
doDisconnect();
- NdbGlobalEventBuffer_drop(theGlobalEventBufferHandle);
-
if (TransporterFacade::instance() != NULL && theNdbBlockNumber > 0){
TransporterFacade::instance()->close(theNdbBlockNumber, theFirstTransId);
}
@@ -206,19 +132,6 @@ Ndb::~Ndb()
delete theImpl;
- /**
- * This needs to be put after delete theImpl
- * as TransporterFacade::instance is delete by global_ndb_cluster_connection
- * and used by theImpl
- */
- if (global_ndb_cluster_connection != 0) {
- theNoOfNdbObjects--;
- if(theNoOfNdbObjects == 0){
- delete global_ndb_cluster_connection;
- global_ndb_cluster_connection= 0;
- }
- }//if
-
/**
* This sleep is to make sure that the transporter
* send thread will come in and send any
diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp
index 3001561a73a..f82348fc91d 100644
--- a/ndb/src/ndbapi/Ndblist.cpp
+++ b/ndb/src/ndbapi/Ndblist.cpp
@@ -19,7 +19,6 @@
#include <NdbOperation.hpp>
#include <NdbIndexOperation.hpp>
#include <NdbIndexScanOperation.hpp>
-#include <NdbConnection.hpp>
#include "NdbApiSignal.hpp"
#include <NdbRecAttr.hpp>
#include "NdbUtil.hpp"
@@ -51,10 +50,10 @@ Ndb::checkFailedNode()
/**
* Release all connections in idle list (for node)
*/
- NdbConnection * tNdbCon = theConnectionArray[node_id];
+ NdbTransaction * tNdbCon = theConnectionArray[node_id];
theConnectionArray[node_id] = NULL;
while (tNdbCon != NULL) {
- NdbConnection* tempNdbCon = tNdbCon;
+ NdbTransaction* tempNdbCon = tNdbCon;
tNdbCon = tNdbCon->next();
releaseNdbCon(tempNdbCon);
}
@@ -71,7 +70,7 @@ Ndb::checkFailedNode()
* if createConIdleList was succesful
* Return -1: In all other case.
* Parameters: aNrOfCon : Number of connections offered to the application.
- * Remark: Create connection idlelist with NdbConnection objects.
+ * Remark: Create connection idlelist with NdbTransaction objects.
***************************************************************************/
int
Ndb::createConIdleList(int aNrOfCon)
@@ -123,23 +122,16 @@ Ndb::getNdbCall()
}
/***************************************************************************
- * NdbConnection* getNdbCon();
+ * NdbTransaction* getNdbCon();
*
* Return Value: Return a connection if the getNdbCon was successful.
* Return NULL : In all other case.
* Remark: Get a connection from theConIdleList and return the object .
***************************************************************************/
-NdbConnection*
+NdbTransaction*
Ndb::getNdbCon()
{
- NdbConnection* tNdbCon = theImpl->theConIdleList.seize(this);
- if (unlikely(theImpl->theConIdleList.m_alloc_cnt > theMaxNoOfTransactions))
- {
- theImpl->theConIdleList.release(tNdbCon);
- ndbout << "theNoOfAllocatedTransactions = " << theNoOfAllocatedTransactions << " theMaxNoOfTransactions = " << theMaxNoOfTransactions << endl;
- return NULL;
- }//if
-
+ NdbTransaction* tNdbCon = theImpl->theConIdleList.seize(this);
tNdbCon->theMagicNumber = 0x37412619;
return tNdbCon;
}
@@ -290,13 +282,13 @@ Ndb::releaseNdbCall(NdbCall* aNdbCall)
}
/***************************************************************************
-void releaseNdbCon(NdbConnection* aNdbCon);
+void releaseNdbCon(NdbTransaction* aNdbCon);
-Parameters: aNdbCon: The NdbConnection object.
+Parameters: aNdbCon: The NdbTransaction object.
Remark: Add a Connection object into the signal idlelist.
***************************************************************************/
void
-Ndb::releaseNdbCon(NdbConnection* aNdbCon)
+Ndb::releaseNdbCon(NdbTransaction* aNdbCon)
{
aNdbCon->theMagicNumber = 0xFE11DD;
theImpl->theConIdleList.release(aNdbCon);
@@ -368,9 +360,20 @@ Remark: Add a NdbScanOperation object into the signal idlelist.
void
Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation)
{
+ DBUG_ENTER("Ndb::releaseScanOperation");
+ DBUG_PRINT("enter", ("op=%x", (UintPtr)aScanOperation));
+#ifdef ndb_release_check_dup
+ { NdbIndexScanOperation* tOp = theScanOpIdleList;
+ while (tOp != NULL) {
+ assert(tOp != aScanOperation);
+ tOp = (NdbIndexScanOperation*)tOp->theNext;
+ }
+ }
+#endif
aScanOperation->theNdbCon = NULL;
aScanOperation->theMagicNumber = 0xFE11D2;
theImpl->theScanOpIdleList.release(aScanOperation);
+ DBUG_VOID_RETURN;
}
/***************************************************************************
@@ -426,18 +429,19 @@ Ndb::releaseSignalsInList(NdbApiSignal** pList){
void
Ndb::releaseNdbBlob(NdbBlob* aBlob)
{
+ aBlob->release();
theImpl->theNdbBlobIdleList.release(aBlob);
}
/****************************************************************************
-int releaseConnectToNdb(NdbConnection* aConnectConnection);
+int releaseConnectToNdb(NdbTransaction* aConnectConnection);
Return Value: -1 if error
Parameters: aConnectConnection : Seized schema connection to DBTC
Remark: Release and disconnect from DBTC a connection and seize it to theConIdleList.
*****************************************************************************/
void
-Ndb::releaseConnectToNdb(NdbConnection* a_con)
+Ndb::releaseConnectToNdb(NdbTransaction* a_con)
{
DBUG_ENTER("Ndb::releaseConnectToNdb");
NdbApiSignal tSignal(theMyRef);
@@ -455,7 +459,7 @@ Ndb::releaseConnectToNdb(NdbConnection* a_con)
tSignal.setData((tConPtr = a_con->getTC_ConnectPtr()), 1);
tSignal.setData(theMyRef, 2);
tSignal.setData(a_con->ptr2int(), 3);
- a_con->Status(NdbConnection::DisConnecting);
+ a_con->Status(NdbTransaction::DisConnecting);
a_con->theMagicNumber = 0x37412619;
int ret_code = sendRecSignal(node_id,
WAIT_TC_RELEASE,
diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp
index 0369876f9d8..7554111f4bd 100644
--- a/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/ndb/src/ndbapi/TransporterFacade.cpp
@@ -63,13 +63,16 @@ TransporterFacade* TransporterFacade::theFacadeInstance = NULL;
*****************************************************************************/
void
-reportError(void * callbackObj, NodeId nodeId, TransporterError errorCode){
+reportError(void * callbackObj, NodeId nodeId,
+ TransporterError errorCode, const char *info)
+{
#ifdef REPORT_TRANSPORTER
- ndbout_c("REPORT_TRANSP: reportError (nodeId=%d, errorCode=%d)",
- (int)nodeId, (int)errorCode);
+ ndbout_c("REPORT_TRANSP: reportError (nodeId=%d, errorCode=%d) %s",
+ (int)nodeId, (int)errorCode, info ? info : "");
#endif
- if(errorCode & 0x8000) {
- ndbout_c("reportError (%d, %d)\n", (int)nodeId, (int)errorCode);
+ if(errorCode & TE_DO_DISCONNECT) {
+ ndbout_c("reportError (%d, %d) %s", (int)nodeId, (int)errorCode,
+ info ? info : "");
((TransporterFacade*)(callbackObj))->doDisconnect(nodeId);
}
}
@@ -127,6 +130,10 @@ reportDisconnect(void * callbackObj, NodeId nodeId, Uint32 error){
//TransporterFacade::instance()->reportDisconnected(nodeId);
}
+void
+transporter_recv_from(void * callbackObj, NodeId nodeId){
+ ((TransporterFacade*)(callbackObj))->hb_received(nodeId);
+}
/****************************************************************************
*
@@ -529,43 +536,32 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
iter.first();
theClusterMgr->init(iter);
- /**
- * Unless there is a "Name", the initiated transporter is within
- * an NDB Cluster. (If "Name" is defined, then the transporter
- * is used to connect to a different system, i.e. NDB Cluster.)
- */
-#if 0
- if (!props->contains("Name")) {
-#endif
- iter.first();
- if(iter.find(CFG_NODE_ID, nodeId)){
- TRP_DEBUG( "Node info missing from config." );
- DBUG_RETURN(false);
- }
-
- Uint32 rank = 0;
- if(!iter.get(CFG_NODE_ARBIT_RANK, &rank) && rank>0){
- theArbitMgr = new ArbitMgr(* this);
- theArbitMgr->setRank(rank);
- Uint32 delay = 0;
- iter.get(CFG_NODE_ARBIT_DELAY, &delay);
- theArbitMgr->setDelay(delay);
- }
- Uint32 scan_batch_size= 0;
- if (!iter.get(CFG_MAX_SCAN_BATCH_SIZE, &scan_batch_size)) {
- m_scan_batch_size= scan_batch_size;
- }
- Uint32 batch_byte_size= 0;
- if (!iter.get(CFG_BATCH_BYTE_SIZE, &batch_byte_size)) {
- m_batch_byte_size= batch_byte_size;
- }
- Uint32 batch_size= 0;
- if (!iter.get(CFG_BATCH_SIZE, &batch_size)) {
- m_batch_size= batch_size;
- }
-#if 0
+ iter.first();
+ if(iter.find(CFG_NODE_ID, nodeId)){
+ TRP_DEBUG( "Node info missing from config." );
+ DBUG_RETURN(false);
+ }
+
+ Uint32 rank = 0;
+ if(!iter.get(CFG_NODE_ARBIT_RANK, &rank) && rank>0){
+ theArbitMgr = new ArbitMgr(* this);
+ theArbitMgr->setRank(rank);
+ Uint32 delay = 0;
+ iter.get(CFG_NODE_ARBIT_DELAY, &delay);
+ theArbitMgr->setDelay(delay);
+ }
+ Uint32 scan_batch_size= 0;
+ if (!iter.get(CFG_MAX_SCAN_BATCH_SIZE, &scan_batch_size)) {
+ m_scan_batch_size= scan_batch_size;
+ }
+ Uint32 batch_byte_size= 0;
+ if (!iter.get(CFG_BATCH_BYTE_SIZE, &batch_byte_size)) {
+ m_batch_byte_size= batch_byte_size;
+ }
+ Uint32 batch_size= 0;
+ if (!iter.get(CFG_BATCH_SIZE, &batch_size)) {
+ m_batch_size= batch_size;
}
-#endif
Uint32 timeout = 120000;
iter.first();
diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp
index b8963b8d0e1..48e1c8ed25f 100644
--- a/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/ndb/src/ndbapi/TransporterFacade.hpp
@@ -24,6 +24,7 @@
#include <NdbMutex.h>
#include "DictCache.hpp"
#include <BlockNumbers.h>
+#include <mgmapi.h>
class ClusterMgr;
class ArbitMgr;
@@ -43,10 +44,6 @@ extern "C" {
void atexit_stop_instance();
}
-/**
- * Max number of Ndb objects in different threads.
- * (Ndb objects should not be shared by different threads.)
- */
class TransporterFacade
{
public:
@@ -115,6 +112,11 @@ public:
Uint32 get_batch_byte_size();
Uint32 get_batch_size();
+ TransporterRegistry* get_registry() { return theTransporterRegistry;};
+
+ // heart beat received from a node (e.g. a signal came)
+ void hb_received(NodeId n);
+
private:
/**
* Send a signal unconditional of node status (used by ClusterMgr)
@@ -128,13 +130,13 @@ private:
friend class GrepSS;
friend class Ndb;
friend class Ndb_cluster_connection_impl;
- friend class NdbConnection;
+ friend class NdbTransaction;
int sendSignalUnCond(NdbApiSignal *, NodeId nodeId);
bool isConnected(NodeId aNodeId);
void doStop();
-
+
TransporterRegistry* theTransporterRegistry;
SocketServer m_socket_server;
int sendPerformedLastInterval;
@@ -172,6 +174,10 @@ private:
* Block number handling
*/
public:
+ /**
+ * Max number of Ndb objects.
+ * (Ndb objects should not be shared by different threads.)
+ */
STATIC_CONST( MAX_NO_THREADS = 4711 );
Uint32 m_waitfor_timeout; // in milli seconds...
private:
@@ -301,6 +307,12 @@ TransporterFacade::get_node_alive(NodeId n) const {
}
inline
+void
+TransporterFacade::hb_received(NodeId n) {
+ theClusterMgr->hb_received(n);
+}
+
+inline
bool
TransporterFacade::get_node_stopping(NodeId n) const {
const ClusterMgr::Node & node = theClusterMgr->getNodeInfo(n);
diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp
index df744fb3261..1e53558f179 100644
--- a/ndb/src/ndbapi/ndb_cluster_connection.cpp
+++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp
@@ -28,7 +28,8 @@
#include <ndb_limits.h>
#include <ConfigRetriever.hpp>
#include <ndb_version.h>
-#include <Vector.hpp>
+#include <mgmapi_debug.h>
+#include <mgmapi_internal.h>
#include <md5_hash.hpp>
#include <EventLogger.hpp>
@@ -85,7 +86,7 @@ const char *Ndb_cluster_connection::get_connectstring(char *buf,
return 0;
}
-extern "C" pthread_handler_decl(run_ndb_cluster_connection_connect_thread, me)
+pthread_handler_t run_ndb_cluster_connection_connect_thread(void *me)
{
g_run_connect_thread= 1;
((Ndb_cluster_connection_impl*) me)->connect_thread();
@@ -180,6 +181,12 @@ Ndb_cluster_connection::no_db_nodes()
return m_impl.m_all_nodes.size();
}
+unsigned
+Ndb_cluster_connection::node_id()
+{
+ return m_impl.m_transporter_facade->ownId();
+}
+
int
Ndb_cluster_connection::wait_until_ready(int timeout,
@@ -251,7 +258,8 @@ unsigned Ndb_cluster_connection::get_connect_count() const
Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char *
connect_string)
: Ndb_cluster_connection(*this),
- m_optimized_node_selection(1)
+ m_optimized_node_selection(1),
+ m_name(0)
{
DBUG_ENTER("Ndb_cluster_connection");
DBUG_PRINT("enter",("Ndb_cluster_connection this=0x%x", this));
@@ -259,22 +267,16 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char *
g_eventLogger.createConsoleHandler();
g_eventLogger.setCategory("NdbApi");
g_eventLogger.enable(Logger::LL_ON, Logger::LL_ERROR);
-
- m_transporter_facade=
- TransporterFacade::theFacadeInstance= new TransporterFacade();
m_connect_thread= 0;
m_connect_callback= 0;
if (ndb_global_event_buffer_mutex == NULL)
- {
ndb_global_event_buffer_mutex= NdbMutex_Create();
- }
+
#ifdef VM_TRACE
if (ndb_print_state_mutex == NULL)
- {
ndb_print_state_mutex= NdbMutex_Create();
- }
#endif
m_config_retriever=
new ConfigRetriever(connect_string, NDB_VERSION, NODE_TYPE_API);
@@ -285,14 +287,21 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char *
delete m_config_retriever;
m_config_retriever= 0;
}
-
+ if (m_name)
+ {
+ NdbMgmHandle h= m_config_retriever->get_mgmHandle();
+ ndb_mgm_set_name(h, m_name);
+ }
+ m_transporter_facade=
+ TransporterFacade::theFacadeInstance=
+ new TransporterFacade();
+
DBUG_VOID_RETURN;
}
Ndb_cluster_connection_impl::~Ndb_cluster_connection_impl()
{
DBUG_ENTER("~Ndb_cluster_connection");
- DBUG_PRINT("enter",("~Ndb_cluster_connection this=0x%x", this));
TransporterFacade::stop_instance();
if (m_connect_thread)
{
@@ -310,10 +319,10 @@ Ndb_cluster_connection_impl::~Ndb_cluster_connection_impl()
TransporterFacade::theFacadeInstance= 0;
}
if (m_config_retriever)
+ {
delete m_config_retriever;
-
- // fragmentToNodeMap.release();
-
+ m_config_retriever= NULL;
+ }
if (ndb_global_event_buffer_mutex != NULL)
{
NdbMutex_Destroy(ndb_global_event_buffer_mutex);
@@ -326,11 +335,26 @@ Ndb_cluster_connection_impl::~Ndb_cluster_connection_impl()
ndb_print_state_mutex= NULL;
}
#endif
+ if (m_name)
+ free(m_name);
DBUG_VOID_RETURN;
}
void
+Ndb_cluster_connection_impl::set_name(const char *name)
+{
+ if (m_name)
+ free(m_name);
+ m_name= strdup(name);
+ if (m_config_retriever && m_name)
+ {
+ NdbMgmHandle h= m_config_retriever->get_mgmHandle();
+ ndb_mgm_set_name(h, m_name);
+ }
+}
+
+void
Ndb_cluster_connection_impl::init_nodes_vector(Uint32 nodeid,
const ndb_mgm_configuration
&config)
@@ -481,9 +505,16 @@ Ndb_cluster_connection_impl::do_test()
delete [] nodes;
}
+void Ndb_cluster_connection::set_name(const char *name)
+{
+ m_impl.set_name(name);
+}
+
int Ndb_cluster_connection::connect(int no_retries, int retry_delay_in_seconds,
int verbose)
{
+ struct ndb_mgm_reply mgm_reply;
+
DBUG_ENTER("Ndb_cluster_connection::connect");
const char* error = 0;
do {
@@ -501,10 +532,24 @@ int Ndb_cluster_connection::connect(int no_retries, int retry_delay_in_seconds,
ndb_mgm_configuration * props = m_impl.m_config_retriever->getConfig();
if(props == 0)
break;
- m_impl.m_transporter_facade->start_instance(nodeId, props);
+ m_impl.m_transporter_facade->start_instance(nodeId, props);
m_impl.init_nodes_vector(nodeId, *props);
+ for(unsigned i=0;
+ i<m_impl.m_transporter_facade->get_registry()->m_transporter_interface.size();
+ i++)
+ ndb_mgm_set_connection_int_parameter(m_impl.m_config_retriever->get_mgmHandle(),
+ nodeId,
+ m_impl.m_transporter_facade->get_registry()
+ ->m_transporter_interface[i]
+ .m_remote_nodeId,
+ CFG_CONNECTION_SERVER_PORT,
+ m_impl.m_transporter_facade->get_registry()
+ ->m_transporter_interface[i]
+ .m_s_service_port,
+ &mgm_reply);
+
ndb_mgm_destroy_configuration(props);
m_impl.m_transporter_facade->connected();
DBUG_RETURN(0);
@@ -541,110 +586,5 @@ void Ndb_cluster_connection_impl::connect_thread()
DBUG_VOID_RETURN;
}
-/*
- * Hint handling to select node
- * ToDo: fix this
- */
-
-void
-Ndb_cluster_connection_impl::FragmentToNodeMap::init(Uint32 noOfNodes,
- Uint8 nodeIds[])
-{
- kValue = 6;
- noOfFragments = 2 * noOfNodes;
-
- /**
- * Compute hashValueMask and hashpointerValue
- */
- {
- Uint32 topBit = (1 << 31);
- for(int i = 31; i>=0; i--){
- if((noOfFragments & topBit) != 0)
- break;
- topBit >>= 1;
- }
- hashValueMask = topBit - 1;
- hashpointerValue = noOfFragments - (hashValueMask + 1);
- }
-
- /**
- * This initialization depends on
- * the fact that:
- * primary node for fragment i = i % noOfNodes
- *
- * This algorithm should be implemented in Dbdih
- */
- {
- if (fragment2PrimaryNodeMap != 0)
- abort();
-
- fragment2PrimaryNodeMap = new Uint32[noOfFragments];
- Uint32 i;
- for(i = 0; i<noOfNodes; i++){
- fragment2PrimaryNodeMap[i] = nodeIds[i];
- }
-
- // Sort them (bubble sort)
- for(i = 0; i<noOfNodes-1; i++)
- for(Uint32 j = i+1; j<noOfNodes; j++)
- if(fragment2PrimaryNodeMap[i] > fragment2PrimaryNodeMap[j]){
- Uint32 tmp = fragment2PrimaryNodeMap[i];
- fragment2PrimaryNodeMap[i] = fragment2PrimaryNodeMap[j];
- fragment2PrimaryNodeMap[j] = tmp;
- }
-
- for(i = 0; i<noOfNodes; i++){
- fragment2PrimaryNodeMap[i+noOfNodes] = fragment2PrimaryNodeMap[i];
- }
- }
-}
-
-void
-Ndb_cluster_connection_impl::FragmentToNodeMap::release(){
- delete [] fragment2PrimaryNodeMap;
- fragment2PrimaryNodeMap = 0;
-}
-
-static const Uint32 MAX_KEY_LEN_64_WORDS = 4;
-Uint32
-Ndb_cluster_connection_impl::guess_primary_node(const char *keyData,
- Uint32 keyLen)
-{
- Uint64 tempData[MAX_KEY_LEN_64_WORDS];
-
- const Uint32 usedKeyLen = (keyLen + 3) >> 2; // In words
- const char * usedKeyData = 0;
-
- /**
- * If key data buffer is not aligned (on 64 bit boundary)
- * or key len is not a multiple of 4
- * Use temp data
- */
- if(((((UintPtr)keyData) & 7) == 0) && ((keyLen & 3) == 0)) {
- usedKeyData = keyData;
- } else {
- memcpy(&tempData[0], keyData, keyLen);
- const int slack = keyLen & 3;
- if(slack > 0) {
- memset(&((char *)&tempData[0])[keyLen], 0, (4 - slack));
- }//if
- usedKeyData = (char *)&tempData[0];
- }//if
-
- Uint32 hashValue = md5_hash((Uint64 *)usedKeyData, usedKeyLen);
-
- hashValue >>= fragmentToNodeMap.kValue;
-
- Uint32 fragmentId = hashValue &
- fragmentToNodeMap.hashValueMask;
-
- if(fragmentId < fragmentToNodeMap.hashpointerValue) {
- fragmentId = hashValue &
- ((fragmentToNodeMap.hashValueMask << 1) + 1);
- }//if
- return fragmentId;
-}
-
-
template class Vector<Ndb_cluster_connection_impl::Node>;
diff --git a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
index ee561c1d6af..a50d3004364 100644
--- a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
+++ b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp
@@ -55,22 +55,6 @@ private:
friend class NdbImpl;
friend void* run_ndb_cluster_connection_connect_thread(void*);
friend class Ndb_cluster_connection;
-
- /**
- * Structure containing values for guessing primary node
- */
- struct FragmentToNodeMap {
- FragmentToNodeMap():
- fragment2PrimaryNodeMap(0) {};
- Uint32 kValue;
- Uint32 hashValueMask;
- Uint32 hashpointerValue;
- Uint32 noOfFragments;
- Uint32 *fragment2PrimaryNodeMap;
-
- void init(Uint32 noOfNodes, Uint8 nodeIds[]);
- void release();
- } fragmentToNodeMap;
struct Node
{
@@ -86,9 +70,8 @@ private:
Vector<Node> m_all_nodes;
void init_nodes_vector(Uint32 nodeid, const ndb_mgm_configuration &config);
- Uint32 guess_primary_node(const char * keyData, Uint32 keyLen);
-
void connect_thread();
+ void set_name(const char *name);
TransporterFacade *m_transporter_facade;
ConfigRetriever *m_config_retriever;
@@ -96,6 +79,7 @@ private:
int (*m_connect_callback)(void);
int m_optimized_node_selection;
+ char *m_name;
};
#endif
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index dea1b8c40ae..946e6fe4cc2 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -55,6 +55,8 @@ typedef struct ErrorBundle {
#define NI ndberror_cl_function_not_implemented
#define UE ndberror_cl_unknown_error_code
+#define OE ndberror_cl_schema_object_already_exists
+
static const char* empty_string = "";
/*
@@ -66,6 +68,7 @@ static const char* empty_string = "";
* 600 - ACC
* 700 - DICT
* 800 - TUP
+ * 900 - TUX
* 1200 - LQH
* 1300 - BACKUP
* 4000 - API
@@ -75,6 +78,7 @@ static const char* empty_string = "";
* 4400 - ""
* 4500 - ""
* 4600 - ""
+ * 4700 - "" Event
* 5000 - Management server
*/
@@ -174,11 +178,13 @@ ErrorBundle ErrorCodes[] = {
{ 623, IS, "623" },
{ 624, IS, "624" },
{ 625, IS, "Out of memory in Ndb Kernel, hash index part (increase IndexMemory)" },
- { 800, IS, "Too many ordered indexes (increase MaxNoOfOrderedIndexes)" },
+ { 640, IS, "Too many hash indexes (should not happen)" },
{ 826, IS, "Too many tables and attributes (increase MaxNoOfAttributes or MaxNoOfTables)" },
{ 827, IS, "Out of memory in Ndb Kernel, table data (increase DataMemory)" },
{ 902, IS, "Out of memory in Ndb Kernel, ordered index data (increase DataMemory)" },
- { 832, IS, "832" },
+ { 903, IS, "Too many ordered indexes (increase MaxNoOfOrderedIndexes)" },
+ { 904, IS, "Out of fragment records (increase MaxNoOfOrderedIndexes)" },
+ { 905, IS, "Out of attribute records (increase MaxNoOfAttributes)" },
/**
* TimeoutExpired
@@ -204,6 +210,7 @@ ErrorBundle ErrorCodes[] = {
* Internal errors
*/
{ 892, IE, "Inconsistent hash index. The index needs to be dropped and recreated" },
+ { 896, IE, "Tuple corrupted - wrong checksum or column data in invalid format" },
{ 901, IE, "Inconsistent ordered index. The index needs to be dropped and recreated" },
{ 202, IE, "202" },
{ 203, IE, "203" },
@@ -220,6 +227,7 @@ ErrorBundle ErrorCodes[] = {
{ 277, IE, "277" },
{ 278, IE, "278" },
{ 287, IE, "Index corrupted" },
+ { 290, IE, "Corrupt key in TC, unable to xfrm" },
{ 631, IE, "631" },
{ 632, IE, "632" },
{ 702, IE, "Request to non-master" },
@@ -258,7 +266,9 @@ ErrorBundle ErrorCodes[] = {
/**
* Application error
*/
+ { 763, AE, "Alter table requires cluster nodes to have exact same version" },
{ 823, AE, "Too much attrinfo from application in tuple manager" },
+ { 831, AE, "Too many nullable/bitfields in table definition" },
{ 876, AE, "876" },
{ 877, AE, "877" },
{ 878, AE, "878" },
@@ -270,7 +280,7 @@ ErrorBundle ErrorCodes[] = {
{ 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" },
{ 4256, AE, "Must call Ndb::init() before this function" },
{ 4257, AE, "Tried to read too much - too many getValue calls" },
-
+
/**
* Scan application errors
*/
@@ -287,29 +297,53 @@ ErrorBundle ErrorCodes[] = {
{ 4608, AE, "You can not takeOverScan unless you have used openScanExclusive"},
{ 4609, AE, "You must call nextScanResult before trying to takeOverScan"},
{ 4232, AE, "Parallelism can only be between 1 and 240" },
- { 290, AE, "Scan not started or has been closed by kernel due to timeout" },
+
+ /**
+ * Event schema errors
+ */
+
+ { 4713, SE, "Column defined in event does not exist in table"},
+
+ /**
+ * Event application errors
+ */
+
+ { 4707, AE, "Too many event have been defined"},
+ { 4708, AE, "Event name is too long"},
+ { 4709, AE, "Can't accept more subscribers"},
+ { 746, OE, "Event name already exists"},
+ { 4710, AE, "Event not found"},
+ { 4711, AE, "Creation of event failed"},
+ { 4712, AE, "Stopped event operation does not exist. Already stopped?"},
+
+ /**
+ * Event internal errors
+ */
+
+ { 4731, IE, "Event not found"},
/**
* SchemaError
*/
{ 701, SE, "System busy with other schema operation" },
+ { 711, SE, "System busy with node restart, schema operations not allowed" },
{ 703, SE, "Invalid table format" },
{ 704, SE, "Attribute name too long" },
{ 705, SE, "Table name too long" },
{ 707, SE, "No more table metadata records (increase MaxNoOfTables)" },
{ 708, SE, "No more attribute metadata records (increase MaxNoOfAttributes)" },
{ 709, SE, "No such table existed" },
- { 721, SE, "Table or index with given name already exists" },
+ { 721, OE, "Table or index with given name already exists" },
{ 723, SE, "No such table existed" },
- { 736, SE, "Wrong attribute size" },
+ { 736, SE, "Unsupported array size" },
{ 737, SE, "Attribute array size too big" },
{ 738, SE, "Record too big" },
{ 739, SE, "Unsupported primary key length" },
{ 740, SE, "Nullable primary key not supported" },
{ 741, SE, "Unsupported alter table" },
- { 742, SE, "Unsupported attribute type in index" },
{ 743, SE, "Unsupported character set in table or index" },
{ 744, SE, "Character string is invalid for given character set" },
+ { 745, SE, "Distribution key not supported for char attribute (use binary attribute)" },
{ 761, SE, "Unable to drop table as backup is in progress" },
{ 762, SE, "Unable to alter table as backup is in progress" },
{ 241, SE, "Invalid schema object version" },
@@ -317,6 +351,9 @@ ErrorBundle ErrorCodes[] = {
{ 284, SE, "Table not defined in transaction coordinator" },
{ 285, SE, "Unknown table error in transaction coordinator" },
{ 881, SE, "Unable to create table, out of data pages (increase DataMemory) " },
+ { 906, SE, "Unsupported attribute type in index" },
+ { 907, SE, "Unsupported character set in table or index" },
+ { 908, IS, "Invalid ordered index tree node size" },
{ 1225, SE, "Table not defined in local query handler" },
{ 1226, SE, "Table is being dropped" },
{ 1228, SE, "Cannot use drop table for drop index" },
@@ -461,8 +498,7 @@ ErrorBundle ErrorCodes[] = {
{ 4241, AE, "Index name too long" },
{ 4242, AE, "Too many indexes" },
{ 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"},
+ { 4244, OE, "Index or table with given name already exists" },
{ 4247, AE, "Illegal index/trigger create/drop/alter request" },
{ 4248, AE, "Trigger/index name invalid" },
{ 4249, AE, "Invalid table" },
@@ -479,13 +515,15 @@ ErrorBundle ErrorCodes[] = {
{ 4262, UD, "NdbScanFilter: Condition is out of bounds"},
{ 4263, IE, "Invalid blob attributes or invalid blob parts table" },
{ 4264, AE, "Invalid usage of blob attribute" },
- { 4265, AE, "Method is not valid in current blob state" },
+ { 4265, AE, "The blob method is not valid in current blob state" },
{ 4266, AE, "Invalid blob seek position" },
{ 4267, IE, "Corrupted blob value" },
{ 4268, IE, "Error in blob head update forced rollback of transaction" },
- { 4268, IE, "Unknown blob error" },
{ 4269, IE, "No connection to ndb management server" },
- { 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" }
+ { 4270, IE, "Unknown blob error" },
+ { 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" },
+ { 4271, AE, "Invalid index object, not retrieved via getIndex()" },
+ { 4275, AE, "The blob method is incompatible with operation type or lock mode" }
};
static
@@ -656,5 +694,7 @@ int ndb_error_string(int err_no, char *str, unsigned int size)
ndberror_classification_message(error.classification));
str[size-1]= '\0';
- return len;
+ if (error.classification != UE)
+ return len;
+ return -len;
}